Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- 9625 discussions
25 Feb '09
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-02-25 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Fix DICOM implementation: was DCMTK, now is GDCM.
* mln/io/dicom/load.hh: GDCM version.
---
load.hh | 338 ++++++++++++----------------------------------------------------
1 file changed, 65 insertions(+), 273 deletions(-)
Index: trunk/milena/mln/io/dicom/load.hh
===================================================================
--- trunk/milena/mln/io/dicom/load.hh (revision 3422)
+++ trunk/milena/mln/io/dicom/load.hh (revision 3423)
@@ -25,72 +25,27 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*
- *
- * Copyright (C) 1994-2005, OFFIS
- *
- * This software and supporting documentation were developed by
- *
- * Kuratorium OFFIS e.V.
- * Healthcare Information and Communication Systems
- * Escherweg 2
- * D-26121 Oldenburg, Germany
- *
- * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY
- * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
- * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
- * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
- * PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
- *
- * Module: dcmdata
- *
- * Author: Gerd Ehlers
- *
- * Purpose: List the contents of a dicom file
- *
- * Last Update: $Author: meichel $
- * Update Date: $Date: 2005/12/08 15:40:46 $
- * CVS/RCS Revision: $Revision: 1.55 $
- * Status: $State: Exp $
- *
- * CVS/RCS Log at end of file
- *
- */
-
#ifndef MLN_IO_DICOM_LOAD_HH
# define MLN_IO_DICOM_LOAD_HH
/*!
- * \file mln/io/dicom/load.hh
+ * \file mln/io/magick/load.hh
*
- * \brief Define a function which loads an image of kind dicom with
+ * \brief Define a function which loads an image of kind magick with
* given path.
*
*/
-# include <mln/io/pnm/load.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image3d.hh>
-# include <dcmtk/config/osconfig.h> /* make sure OS specific configuration is included first */
-# include <dcmtk/ofstd/ofstream.h>
-# include <dcmtk/dcmdata/dctk.h>
-# include <dcmtk/dcmdata/dcdebug.h>
-# include <dcmtk/dcmdata/cmdlnarg.h>
-# include <dcmtk/ofstd/ofconapp.h>
-# include <dcmtk/dcmdata/dcuid.h> /* for dcmtk version name */
-# include <dcmtk/dcmdata/dcistrmz.h> /* for dcmZlibExpectRFC1950Encoding */
-
-# define INCLUDE_CSTDLIB
-# define INCLUDE_CSTRING
-# include <dcmtk/ofstd/ofstdinc.h>
-
-# ifdef WITH_ZLIB
-# include <zlib.h> /* for zlibVersion() */
-# endif
-
-# define SHORTCOL 3
-# define LONGCOL 20
-# define PATH_SEPARATOR '/'
+# include <mln/algebra/vec.hh>
+# include <gdcmReader.h>
+# include <gdcmImageReader.h>
+# include <gdcmWriter.h>
+# include <gdcmDataSet.h>
+# include <gdcmAttribute.h>
namespace mln
@@ -112,37 +67,15 @@
void load(Image<I>& ima,
const std::string& filename);
- /*! Load a dicom image in a Milena image. To use this routine, you
- * should specialize the template whith the value type of the
- * image loaded. (ex : load<value::int_u8>("...") )
- *
- * \param[in] filename The image source.
- *
- * \return An image2d which contains loaded data.
- */
- template <typename V>
- image2d<V> load(const std::string& filename);
-
- /*! Load a dicom image in a Milena image. To use this routine, you
- * should specialize the template whith the value type of the
- * image loaded. (ex : load<value::int_u8>("...") )
- *
- * \param[in] filename The image source.
- *
- * \return An image2d which contains loaded data.
- */
- template <typename V>
- image3d<V> load(const std::string& filename);
-
# ifndef MLN_INCLUDE_ONLY
template <typename V>
inline
image2d<V> load(const std::string& filename)
{
- trace::entering("mln::io::dicom::load");
- image2d<V> ima;// = io::pnm::load<V>(DICOM, filename);
- trace::exiting("mln::io::dicom::load");
+ trace::entering("mln::io::gdcm::load");
+ image2d<V> ima;// = io::pnm::load<V>(MAGICK, filename);
+ trace::exiting("mln::io::gdcm::load");
return ima;
}
@@ -150,228 +83,87 @@
inline
image3d<V> load(const std::string& filename)
{
- trace::entering("mln::io::dicom::load");
- image2d<V> ima;// = io::pnm::load<V>(DICOM, filename);
- trace::exiting("mln::io::dicom::load");
+ trace::entering("mln::io::gdcm::load");
+ image2d<V> ima;// = io::pnm::load<V>(MAGICK, filename);
+ trace::exiting("mln::io::gdcm::load");
return ima;
}
-
-
-
-
- static OFBool printAllInstances = OFTrue;
- static OFBool prependSequenceHierarchy = OFFalse;
- static int printTagCount = 0;
- static const int MAX_PRINT_TAG_NAMES = 1024;
- static const char* printTagNames[MAX_PRINT_TAG_NAMES];
- static const DcmTagKey* printTagKeys[MAX_PRINT_TAG_NAMES];
- static OFCmdUnsignedInt maxReadLength = 4096; // default is 4 KB
-
- static OFBool addPrintTagName(const char* tagName)
- {
- if (printTagCount >= MAX_PRINT_TAG_NAMES) {
- std::cerr << "error: too many print Tag options (max: " << MAX_PRINT_TAG_NAMES << ")" << endl;
- return OFFalse;
- }
-
- unsigned int group = 0xffff;
- unsigned int elem = 0xffff;
- if (sscanf(tagName, "%x,%x", &group, &elem) != 2)
- {
- /* it is a name */
- const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock();
- const DcmDictEntry *dicent = globalDataDict.findEntry(tagName);
- if (dicent == NULL)
- {
- std::cerr << "error: unrecognised tag name: '" << tagName << "'" << endl;
- dcmDataDict.unlock();
- return OFFalse;
- }
- else
- {
- /* note for later */
- printTagKeys[printTagCount] = new DcmTagKey(dicent->getKey());
- }
- dcmDataDict.unlock();
- }
- else
- {
- /* tag name has format xxxx,xxxx */
- /* do not lookup in dictionary, tag could be private */
- printTagKeys[printTagCount] = NULL;
- }
-
- printTagNames[printTagCount] = strcpy(OFstatic_cast(char*, malloc(strlen(tagName)+1)), tagName);
- printTagCount++;
- return OFTrue;
- }
-
-
template <typename I>
- static void printResult(Image<I>& ima, DcmStack& stack, size_t printFlags)
+ inline
+ void load(Image<I>& ima_,
+ const std::string& filename)
{
- unsigned long n = stack.card();
- if (n == 0)
- return;
-
- if (prependSequenceHierarchy) {
- /* print the path leading up to the top stack elem */
- for (unsigned long i = n - 1; i >= 1; i--) {
- DcmObject *dobj = stack.elem(i);
- /* do not print if a DCM_Item as this is not
- * very helpful to distinguish instances.
- */
- if (dobj != NULL && dobj->getTag().getXTag() != DCM_Item) {
- char buf[512];
- sprintf(buf, "(%x,%x).",
- OFstatic_cast(unsigned, dobj->getGTag()),
- OFstatic_cast(unsigned, dobj->getETag()));
- std::cout << buf;
- }
- }
- }
+ trace::entering("mln::io::gdcm::load");
- /* print the tag and its value */
- DcmObject *dobj = stack.top();
- dobj->print(std::cout, printFlags);
- }
+ using value::int_u16;
+ I& ima = exact(ima_);
- template <typename I>
- static int dumpFile(Image<I>& ima,
- const char *ifname,
- const E_FileReadMode readMode,
- const E_TransferSyntax xfer,
- const size_t printFlags,
- const OFBool loadIntoMemory,
- const OFBool stopOnErrors,
- const OFBool writePixelData,
- const char *pixelDirectory)
+ gdcm::ImageReader r;
+ r.SetFileName(filename.c_str());
+ if (!r.Read())
{
- int result = 0;
+ std::cerr << "error: cannot open file '" << filename << "'!";
+ abort();
+ }
- DcmFileFormat dfile;
- DcmObject *dset = &dfile;
+ gdcm::File &file = r.GetFile();
+ gdcm::DataSet& ds = file.GetDataSet();
- if (readMode == ERM_dataset)
- dset = dfile.getDataset();
+ gdcm::Image& image = r.GetImage();
- // Load file
+ char* dataBuffer = new char[image.GetBufferLength()];
+ image.GetBuffer(dataBuffer);
- OFCondition cond = dfile.loadFile(ifname, xfer, EGL_noChange, maxReadLength, readMode);
+ int ndims = image.GetNumberOfDimensions();
+ const unsigned int* dims = image.GetDimensions();
- // Read error
+ unsigned short bytes_allocated = image.GetPixelFormat().GetBitsAllocated() / 8;
+ unsigned short samples_per_pixel = image.GetPixelFormat().GetSamplesPerPixel();
- if (!cond.good())
+ if (mln_site_(I)::dim != ndims)
{
- std::cerr << "error: " << dfile.error().text()
- << ": reading file: "<< ifname << endl;
- result = 1;
- if (stopOnErrors)
- return result;
+ std::cerr << "error: dimension mismatch" << std::endl;
+ abort();
}
- if (loadIntoMemory)
- dfile.loadAllDataIntoMemory();
-
- if (printTagCount == 0)
- {
- if (writePixelData)
- {
- OFString str = ifname;
- OFString rname = pixelDirectory;
- if ((rname.length() > 0) && (rname[rname.length() - 1] != PATH_SEPARATOR))
- rname += PATH_SEPARATOR;
- size_t pos = str.find_last_of(PATH_SEPARATOR);
- if (pos == OFString_npos)
- rname += str;
- else
- rname += str.substr(pos + 1);
- size_t counter = 0;
- dset->print(std::cout, printFlags, 0 /*level*/, rname.c_str(), &counter);
- }
- else
- dset->print(std::cout, printFlags);
- }
- else
- {
- /* only print specified tags */
- for (int i = 0; i < printTagCount; i++)
+ algebra::vec<mln_site_(I)::dim, unsigned int> vmin;
+ algebra::vec<mln_site_(I)::dim, unsigned int> vmax;
+ algebra::vec<mln_site_(I)::dim, unsigned int> vdims;
+ for (int i = ndims - 1; i >= 0; --i)
{
- unsigned int group = 0xffff;
- unsigned int elem = 0xffff;
- DcmTagKey searchKey;
- const char* tagName = printTagNames[i];
- if (printTagKeys[i])
- searchKey = *printTagKeys[i];
+ vmin[i] = 0;
+ vmax[i] = dims[ndims - i - 1] - 1;
+ if (i == ndims - 1)
+ vdims[i] = 1;
else
- {
- if (sscanf(tagName, "%x,%x", &group, &elem) == 2)
- searchKey.set(group, elem);
- else
- {
- std::cerr << "Internal ERROR in File " << __FILE__ << ", Line "
- << __LINE__ << std::endl
- << "-- Named tag inconsistency" << std::endl;
- abort();
- }
+ vdims[i] = dims[ndims - i - 2] * vdims[i + 1];
}
- DcmStack stack;
- if (dset->search(searchKey, stack, ESM_fromHere, OFTrue) == EC_Normal)
+ mln_site(I) pmin(vmin);
+ mln_site(I) pmax(vmax);
+ mln_concrete(I) result(box<mln_site(I)>(pmin, pmax));
+ initialize(ima, result);
+ mln_piter(I) p(ima.domain());
+ unsigned int index = 0;
+ for_all(p)
{
- printResult(ima, stack, printFlags);
- if (printAllInstances)
+ index = 0;
+ for (int i = 0; i < ndims; ++i)
{
- while (dset->search(searchKey, stack, ESM_afterStackTop, OFTrue) == EC_Normal)
- printResult(ima, stack, printFlags);
- }
+ index += p.to_site().to_vec()[i] * vdims[i];
}
- }
- }
-
- return result;
- }
-
-
- template <typename I>
- inline
- void load(Image<I>& ima,
- const std::string& filename)
+ ima(p) = dataBuffer[index * bytes_allocated * samples_per_pixel];
+ // FIXME: RGB support, HighBit
+ for (int j = 1; j < bytes_allocated; ++j)
{
- trace::entering("mln::io::dicom::load");
-
- std::ifstream file(filename.c_str());
- if (! file)
- {
- std::cerr << "error: cannot open file '" << filename << "'!";
- abort();
+ ima(p) *= 256;
+ ima(p) += dataBuffer[(index * bytes_allocated + j) * samples_per_pixel];
}
-
- int opt_debugMode = 0;
- OFBool loadIntoMemory = OFTrue;
- size_t printFlags = DCMTypes::PF_shortenLongTagValues /*| DCMTypes::PF_showTreeStructure*/;
- OFBool printFilename = OFFalse;
- OFBool writePixelData = OFFalse;
- E_FileReadMode readMode = ERM_autoDetect;
- E_TransferSyntax xfer = EXS_Unknown;
- OFBool stopOnErrors = OFTrue;
- const char *current = NULL;
- const char *pixelDirectory = NULL;
-
-
- /* make sure data dictionary is loaded */
- if (!dcmDataDict.isDictionaryLoaded())
- {
- std::cerr << "Warning: no data dictionary loaded, "
- << "check environment variable: "
- << DCM_DICT_ENVIRONMENT_VARIABLE;
}
- int errorCount = 0;
- dumpFile(ima, current, readMode, xfer, printFlags, loadIntoMemory, stopOnErrors,
- writePixelData, pixelDirectory);
+ delete(dataBuffer);
trace::exiting("mln::io::dicom::load");
}
1
0
* mln/opt/all.hh,
* mln/opt/essential.hh: new.
---
milena/ChangeLog | 21 +++++++++++++++++++++
milena/mln/opt/all.hh | 39 +++++++++++++++++++++++++++++++++++++++
milena/mln/opt/essential.hh | 37 +++++++++++++++++++++++++++++++++++++
3 files changed, 97 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/opt/all.hh
create mode 100644 milena/mln/opt/essential.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 5727ea3..9c8ace6 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,24 @@
+2009-02-25 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Add all.hh and essential.hh in mln/opt.
+
+ * mln/opt/all.hh,
+ * mln/opt/essential.hh: new.
+
+2009-02-24 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Fix step 4 in tutorial.
+
+ * doc/tutorial/figures/tuto4_genericity_and_algorithms-5.ppm,
+ * doc/tutorial/figures/tuto4_genericity_and_algorithms-6.ppm,
+ * doc/tutorial/figures/tuto4_genericity_and_algorithms-9.ppm: update
+ reference file.
+
+ * doc/tutorial/samples/tuto4_genericity_and_algorithms.cc: fix
+ threshold function.
+
+ * doc/tutorial/tutorial.tex: include the proper image in step 4.
+
2009-02-24 Guillaume Lazzara <z(a)lrde.epita.fr>
Various small fixes.
diff --git a/milena/mln/opt/all.hh b/milena/mln/opt/all.hh
new file mode 100644
index 0000000..ac80cd4
--- /dev/null
+++ b/milena/mln/opt/all.hh
@@ -0,0 +1,39 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_OPT_ALL_HH
+# define MLN_OPT_ALL_HH
+
+/// \file mln/opt/all.hh
+///
+/// File that includes the most useful optional routines.
+
+# include <mln/opt/at.hh>
+# include <mln/opt/element.hh>
+# include <mln/opt/value.hh>
+
+#endif // ! MLN_OPT_ALL_HH
diff --git a/milena/mln/opt/essential.hh b/milena/mln/opt/essential.hh
new file mode 100644
index 0000000..f6d144a
--- /dev/null
+++ b/milena/mln/opt/essential.hh
@@ -0,0 +1,37 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_OPT_ESSENTIAL_HH
+# define MLN_OPT_ESSENTIAL_HH
+
+/// \file mln/opt/essential.hh
+///
+/// File that includes the most useful optional routines.
+
+# include <mln/opt/all.hh>
+
+#endif // ! MLN_OPT_ESSENTIAL_HH
--
1.5.6.5
1
0
* doc/tutorial/figures/tuto4_genericity_and_algorithms-5.ppm,
* doc/tutorial/figures/tuto4_genericity_and_algorithms-6.ppm,
* doc/tutorial/figures/tuto4_genericity_and_algorithms-9.ppm: update
reference file.
* doc/tutorial/samples/tuto4_genericity_and_algorithms.cc: fix
threshold function.
* doc/tutorial/tutorial.tex: include the proper image in step 4.
---
.../figures/tuto4_genericity_and_algorithms-5.ppm | Bin 12406 -> 12406 bytes
.../figures/tuto4_genericity_and_algorithms-6.ppm | Bin 12406 -> 12406 bytes
.../figures/tuto4_genericity_and_algorithms-9.ppm | 3 +--
.../samples/tuto4_genericity_and_algorithms.cc | 6 +++---
milena/doc/tutorial/tutorial.tex | 3 +--
5 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/milena/doc/tutorial/figures/tuto4_genericity_and_algorithms-5.ppm b/milena/doc/tutorial/figures/tuto4_genericity_and_algorithms-5.ppm
index 0af91285d61ac6d0cf27b69c8961fabb9ad17644..caa01857a968090f4ef06142068aa3c47e3c090d 100644
GIT binary patch
literal 12406
zcmdUtzl&W}6osv)x6<N55TeB!CnO`-sF)~1lrRKA(Bj3pn!q?SJRd?z!T&*Q)2Fep
zOru~Sq!+<P#DBvr3qBV6oO|xQ&-?rlhQm60uf6tnPu`v5gDc(J{dvDxZ~N2k-ox(Q
z2WS2Hx;t9E+;#W2+sjuE4=?_ztj;#4{i?rwuwAb{*~HYXJMY|mqdVz8@7J4;?|19-
z)9z;fMSpg2`B{Iy?QXB{T}0@`=3#gB_Q}m#FCH9U?~bn@T)T1O;Dx83R{x%v|L@8-
zuf*T<x$0hukrTR|_Q8km<9E@XTB_?Ct9r^O3=J*?+0LnMr}!V|hqEC@KcPC?ezaNL
z=e~Qk;jeD@Vq;b<H={?V8irXRn5!bTM4hv`ltI~atvVY;LaJi7K}|(q5-H7r*`7Q@
zSNu~%HKZIYZQ+Tc&Y`aAq?NWtg{e_dhLj`j@vhfhhleYEDiZ~Rqap?3S3RyFI8!&x
zme;v{Phhqxa7Gs$0<(%-UARB#pMHGe6{fs6MKf567*~;;xVkR89)dH8AlIMQ8T8_)
zW@=Or6;5eJXoXN$Ew8)&SNOqBkX{$$MED(kKWUd1O+R@<<uK@VS`=OI@;m%~l<aA)
zfoTgy+@_)`Za^az=Z~ck?l5z;kE12x^nVFHuHI#@7hMb0E7A-uCCU|1Dd894Uy9jt
z_QxMvJlvNqu6<GU@ppKC=idh~nGPTNf58vDzfuGKZ@zyd`^JXWV>S$GVUyq-di<UF
zV_k#~@qm%2hWtt+5NwGC{BHbOSA}6U9;mARvPc4AL4IHm0I0%J1cs_eIZPqi@N?gv
zb;@@nwKz+Io6&BQPUk<spEkxd@Kl7eA#j#CQQ0ehb)!(D)nN9PLZVWpjl%En`(a&m
zBMeU1)&w$(*ek!bJiWSNor^ZJcQq9i9}hhRe(w91TdMqyCk<q3C1$@a%kO)&CCEqN
zokzON!IK_yAN=f+X!E-{uyut$uF}}{$DfwQMm>JXpPXDlEh|<2iI1N?nQ$^gq+(pv
z)hD<UGlJP6;o}ao6u<9<N=r+Anbq|{*MzuPBm3Y_>td;Par#dvAvrcW1(FkDaekI2
z;Y;C{$6IMCuIfsZe)uQ;c+w}wm5nT-;zC_NOBhdMwv6?VS^PeTW>JW87hU`awYUz=
zVyH&#i9eRIuH>Wz8-mu5z=_Z&w0}RCOW}*urP8>TIaC<03T%jd@Do0f0e=XMc!grL
zQa!Him)F;oQ&bXR)Y+0+er3EWNKhJsRdbuaI^spbwKSdHMf-SF%SkI;sY~pGpA|48
zXf*_87eoGK`O_8$2%Wl(YZ`3KPUpwzd)tfJUC&8+`e0DSENn>-t2$SNFQSO>E}Cvb
zU{0bODZ$E5NS?2M_$vMsRn7nX@cHOQOK0+^UXpmF9Px@fOIo_o3Z3AiB7S{>$5z2q
z9JR4DL^7wV4EPg&Nvp5GFTsC78IJR%w|<pQ9$m4OqU!fzjKo!gL;PSPd{LF(4M`7e
zPd2~$NYY_z^XsF+R)vrHDF63wzUDC6=oqP6y}IAEn}wQA472!o6UJQ(0k}t+93OEl
z+oO{&LnLxtWf+2wF7F?jWK9j7*g_0>NW<V$uEQ|IA1#s3<!^(**0u?93O^nJ>*Ytu
zH8uDB)6@Ctq;XQG;zHfuj^4v2!B;dMKb+!^Gc>U&DqSbq2=sAgU4)_JkD@-o$4k8f
ze}rgznU*R*Qm5h~x<mX7y7*)J5!dPbkB=T{Y9f4?9Wu0!dkdH;!r|rDCxj-mngc)1
ssx1}CYzt*-_Vr)-6ynz%`0sxEb0h@6{*)Fx9y_Gl*r_`dLOsF%2~_1-8vp<R
literal 12406
zcmeIu!3u&v6oui|^As1_)J7}JMY}+Wz(AxI81sgL&B!zazJ2x<E&j7SaL(eZbF-F<
zIt?~zC+#e^VN_>jpX@~X7^hR3`d^cbq0>aCA==~_mQ`6_?`LWBtu{P*v96OsKRWv9
zr7lWkTfdz8Fw3TDigIi6O!CYejz_a12q1s}0tg_000IagfB*srAb<b@2q1s}0tg_0
k00IagfB*srAb<b@2q1s}0tg_000IagfB*srAn^ABU(CBC&Hw-a
diff --git a/milena/doc/tutorial/figures/tuto4_genericity_and_algorithms-6.ppm b/milena/doc/tutorial/figures/tuto4_genericity_and_algorithms-6.ppm
index 5425043a8ddc1022ddaad32b32ef9dc6b55d57c2..84e26814aa767703a034f21fd69960d7874ae55c 100644
GIT binary patch
literal 12406
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
delta 9922
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
diff --git a/milena/doc/tutorial/figures/tuto4_genericity_and_algorithms-9.ppm b/milena/doc/tutorial/figures/tuto4_genericity_and_algorithms-9.ppm
index 5425043..29c0860 100644
--- a/milena/doc/tutorial/figures/tuto4_genericity_and_algorithms-9.ppm
+++ b/milena/doc/tutorial/figures/tuto4_genericity_and_algorithms-9.ppm
@@ -3,5 +3,4 @@ P6
# EPITA Research and Development Laboratory (LRDE)
64 64
255
-âyá
tßlÞnâpéwêtÍde¡>W¬HY°KV²KV±KUºSXÄZZË_\Íb`ÍebÌc_ÍdaÐfbÓeaÐeaÏecÐgcÎgeÌggÌd`ËfcÎc_ÐgaÏeaÍfcÌcaÊcbÊbaÊabÈaa¿[a±QYÁZZØzoÝqÜ~jÝnÞmÞhÞgÝjÝnç¢zùÑ鎩NZžY]Œ\]»^bÁ\]Â^_Â]^Ã`bÃ_^¿Z^ÇniâmâlâkàiånêréjÌ_Z¢;PCR³IS²HQ²HPºQVÄY\Ê^ZÍ_[Íb_Ïc_Ïc]Ðd`Ód_Ñd_ÑdaÐcaÐcaÏdaÎa^Íd`Îb\ÐeaÏc_Îc_Íb`Ë`^Ë`_Ë`_Ê`_Â[`¶RZ²NYÑnkßsàoá
mâ
láiàhÞiÛkÛmõÃúÑÄtg³RY»Z]Ÿ[]¿[]Á\]Ä]]Æ_^Éb`¡DR_AámãkâlánæqçoåkÌb_¡<N¯BNŽIR±GP²FNŒPTÄXYÊ\YÎ`]Ïb]Ðb_Ïb`Ñc^Òc`Òc`Òb^ÒcaÑb`ÐbaÏcaÎc`Îa]ÑgdÏebÎcaÍb^Ía_Ì^]Í`_Í_^Ã]aŒU\°LXÃ`dÛ~sâvãqäpâ
mâlÞjÛ~lÙ}kåuúÑSY¹V[¿Z\¿]^À_aÆbbÏfb?P[B]?âmå
lã
oårçrâoæ
jÎ_W¡8J®BN³HR±HPŽHP»NRÅXXÉ\ZÍ^[Í`]Ï_^ÎaaÑa^Ña_Ó_]ÑaaÒdcÐ\ZÎZWÎ]\Ì][Ë^\Î``ÏcbÏcbÌ_]Ì_^Ì^\Í]\Í_^Å\`ŸV]ŽMXÁ\fÙzuâwâtáoâjálßmÝnÚ~lØzióŒûÖ ÒpŽRWŸ[\À\\À]_Écb<O\B\<d?ã
nänæséqçlãlæ
iÎ^U¡8JBO²GP°FO²EP»OTÄVXÇZZË][Í_]Î][Î__Ò_^Ï``ÐacÑ_^Ò``Ð[ZÊYYÊZXÊZYÇZYË^_ÌacÍceÌ__Î_^Ì]]Í\]Í]]É[_ÀU\·MYÂXbÖspÞtà
tß
oàlànànßmÜ~nØyißjùÒ÷О_bºSWÀ\]Æbb<OZBaEd@b>äpåpèpæfçhånçjÌ]V6JBO³FP±FO²FNŒNTÆWWÇZYË[YË\]Î\\Ð]`Ð]^Ð__Ñ_aÑ]^Ñ__Ð]^ÌacÈikÈqqÅmlÆ]^È\^Ë]`Ì]`Í`cÎ]`Í]]Î]\ÈY]¿S\¹NZÂU_ÔolÚyqÝtßoßnàkálß}jÚxiÙueÖraðŽúÚ§á€~°NV»X]=NZ>^BeD`?]<æoéqåeÞn[ågæoèkÐ^V6H¬>M³FQ±FN·GNÀOTÊVWËYXÎ\YÎ\\Ñ^^Ó^_Ò\^Ð^^Ò^^ÍbhÈu}Ã{ÈÍÒŠÐ¥ÓªÏÆssÄW\É_dÍ^cÍ\_Ì[]ÈW\¿R[·MYÀT]Öni×tmÚyqÞqÞ}mß}jà{gÝveØre×pbÖqbÝjøÎûØ¥Éwh;MX>]?cCaB]=_;épêm×eVÑ]VçjémêkÑ^V1G¥<MAN°CLŽFOŸMTÇTUÉXYÍYXÍ[ZÑ[\Ð]^ÏcfÈntÀbm¿kuÁpvÆz}ÈÌÏÒ¥Ö¬Ù² Þ¹šÑŸ_hÄX`ÇX^ÈW\ÂSYŒNWŽIUÃS[ÙoiÚtkÚvoÛyrÞ{lÜueÜscÛscÙpcØnaÙo`×oaë¡}ý۬݀W>Z?dBaA^A]?`;ísäzc®?IÊYTèiêmêjÑ\S.E 9KªAO¬CO°EQžJRÂPUÄSVÈXZÌZ[ÏYYÐd]ŒS\œ[b»]f¿ioœiqÂnsÃx|Ê
Òէ׬۳¡Ý¶€ÝŒ¬Ø³Šœos¶MWŸPX¿QYžMY²GTÁQ[ÝqjßxlÙsmÖplÚtkÛsgÜpbÝsdÚqcÙpdÚreÚsfÜzkó¹~9LV>bAdB^@^@`?X9ëoÌZT1FÊZVêjëqégÎ[T-D¢;MªCS¬CQ®DP¶KTÀQXÂRVÈUXËWYÒ\[ÆZY»NVœU\Á^dÁchÄjmÃlqÅsvÉ~Ïקگ܎£Þ¹©Ü¹§Ú»°àĹʪJWŽKV²GU¯FVŸP]ßumä~oÞvlË]`Ë]_ÝujßqdßseÜpcÜqeÝsfßviázj0IW=`?d>^>`C_Dd F?Uàr`š;J5HÊ[WéiëoèiÍYS/F€;M¬APER¯DR¶KTÀQUÄTXÉWYÊXYËWX»LSœS\ŸX_ŸZaŸ^dÄhlÆknÆprÌxxÓکܯ ثَ¬à·åË¿æÌŸëÔÅÉ¡<MªCS§AT»O[Þsjä}láynÁTY3JÓffßshàreÝpeÞqgßqfäxk€FSW;`?dA]>c@\Dm+R<XÏ}u¿LM8J6GÉZWç
jëpè
hÌXS0H£=O¬AQDQ¯EQ·JRÀQVÅTWÉWYÉYY»LSºOYŸU\¹T\»X`ÃbfÉlmËppÍssÍwvÔ×Ó Þº±åÈœâŹâÄžãÈŒåÍÁëØÊ±qw7K<PºMXßtlå}názpÄZ`n=±IVÝqjàrgÝoeßqhâshÎc`^A_?gA^?cA]@f$MCeÄwxË|u8J£:J 7JÇXUçjétè
lËZW/F£<M«BQ¬CO°EP·JQÁRVÄTWÊZ[ÀRXŒPX»PXœT[ŒX_ÂafÆhlËnoÍqpÉmoÌssÎ~Ò໯âÀ³á¿ŽÞŒ²áÄžâÄžâÈœäÌÀæÑĶ-D¶ITÞtkä}pâ|rÆY\h>~$BÍ]_ásgÝmcàqiãtiz#CY<iCd@b@`@bFw3YŸqxÉ~zÕ~ :K¢<L9KÆYXålèrç
nË[Y0J¡:L«AODQ®DP·JRÀQW¿QWÒnbŽEPºNVœOVŸT[Á[aÈglÌooÊmoËmpÁcjÃrw؀ീ޵§Û³šÞ¹¯âÞãÄ¹âÆºâǺáÈŒäÎÁé×ÇXhBNÝqgä}oâ{rÇZ^n?_73FÔjdÚtjáti§FRY=d?gA`AaAbAd J·kwÄvwÑ~Õ<M:K5GÃVVælèrç
oË\Z.H8K©>M©AOETµJTœMT¿V\Özi³FTŒMVŸNVÁU]ÈaeËilÊijÉijº[fÅx}ݚܧ۪۫à¹ß»¯àŸ³ÞÀ·ßžßùáÈœáÊÀåÑÅל³9LÛphã|mã|qÆ[^l@X8MfÞœ°åÊŸæÅ·_F]BgCdDbBcB]@¢XnÈxyÏÔ~Ô{;L¥=L€:IÄTTæjêrè
mÊYV+E6J¬@N¯BM°CN¶HQœOUÑ{oÐj_°ESŒMUŸOWÅ\bÅ]bÂ_dÉcdœX_ÏÜØÙ¡Ú€Ý±¥Ü±ŠÝŽªÜµ¬àŒ³á¿ŽàÀµÞÞàÈŸßÈÀåÓɵpvØnfånâ}nÀWY\<rÙ·«æÌ¿êÑÂðÚÉxIf]AeA`>]?dC:\Ë{|Í}Õ}Ô}Ó{©@M¬BN¬>KÇUSåkêsênÌ]Y/E¢:K¯BN³DNŽDN»KQŸMSàyÈ\W¯DQ·IUÁTYÄW^Ä[dÈbfŸYaÓ~y×ÖÛÜ¥Û§Ú©Ø£Û«¡Þީ߹¯ßŒ±Þœ°Ù²©ÝÀ·ÞĺÞÅŒÜÅ¿Ûwå}eÞwd¶^eÀÛ»°åÊŒãÆžâÆºïØÈ~Mf_Ca?_=d?_CÂq{Í~~Ö~Ô|Ó|Ó{COBM®ALÎXRækërìqÏ`X/D£;L¯CN±CM²BKžHNµFPç{ÈYW³FTŽER»MVÄV^ÅX_À[dÒvsÓ|xÍ{{ØÚØÚ¢×ڡ܊ۚܯ¥Ü±š×©Ø²šÛŒ³Üº²Ú»Ž×¹²Ý±Šâ}iÝß»ªÞÀ³âǹàöâÄ·æÌÀîØÆi3V_C_>^=fBKeÐ|}ÔÕ~Ô{Ò|ÒzBO¬AM°AKËXSèkîsîsÑ`X.C¥:I®AL¯@L¯ALµEM±@NôŽ
Õh]ºLS·HTŸMVÅV^ÃXbÑstÒtrËpqÔ~}ÕØØ×ÛÛÙÚ€Ú© Ù§Ø®§Ø³«Ù®ŠÖ©£ÕŠÏ¥¡×Žªßµ€ßŒ¬ãÃŽá¶ßÀ³âĹߺ®åÈœä˺WA`A\>c@1YÍv|ÐÖÕÓ~Ò|Ñ{ªANª@M¬@KÈXTèjítìsÐaY0G¥<K¯AN¯AL°@K³DM²EPõŽßzeÏ]X¶EQ»MWŸR]ÐkmÏqqÇhkÔzwÑyzÑ{|Õ
ÚÚÚÛØ××ـة¢×¥×€¡ÓÑٮܶšáÀ²àŸ°ÞŸ²ßÀŽá÷໮ÔÚ©³Y@_?]<fJ¯]pÐ|}Ô×ÕÓ~Ó}Ô{š@M§>Jª>LÌZWèkëuìqÑcZ0G¥<LAM®@K¯AK±BK±KTô¯{ågØi]ºJSºLWÏjlÊgjÃbiÓrqÎpqÍvwÓz{××
ÖרÔ
ÕØØÖÔÏסݮບߌ«Ýž¬Ý»¯àÁ¶àÞäÈŒÔÎØzC]\?\?aA>bÏ{|ÑÔÓ~ÒÒ}Ò|Ò|ªAN©@N³CMÑ[WékìtípÒe\.C¢;L¬?M?K¯@K¯?I³QW÷ºémáz`ÈVVÉ_cÇciÁ_hÑmnËjmÈiqÎruÓx|¿k}µd~¯fŸvžn~ÏÍÏŒvÆÏÜ¥àŽ€áº§ÚŽ¥Û¹®ÞŸ±á¶âùãǻ޶©»oo±\fÒ§T<^AbCeJ»huÐ||ÕÔ~Ò}Ò}Ñ{Ð|Ð
{¬CPªCP·ENÖ^VêkítîqÕf[-D¡9J¬@M°AM±?K²?H°FOøÀð¢sÙkXÈ[YÀW_ºXdÏikÈeiÆcjÉgmÏouŸez¶`y¢Mo
>p²tQ~Dy?nh$Q_$SŠl|Ø á¶Šß¹©Þº«Úž«ÞŸ±àÀ³ãĶ߻®ÆšQW£GWÖSb\>\>a?~5YÍy|ÒÔÔÒÐÏ|Î
|Ðy°FR®BMžDNÖ^UélìsíqÔfZ/E£:J¬@K¯AL°@L°>I¥6Gò¹ó©xÒf`ÍhgµP]ÍeiÅbjÆ`hÇdlÎinŒ\rº]wHu}4dm$YN}=t}Atg/bRHŠjtÓݰݷ©ÜހܶšÚž«ÝŒ±Þ»Æ¡FT£GVÀjmÝKZ]>a>`?_H¯`pÍ~}ÕÕÓÑÏÐ}Î}Î}²IU°EQ¶CKÓ]VékësípÖh[.E¢9J«>L®ALAL±AJª=IØwöŽÜoÅ__É`hÄ^fÂ[gÄ^hÃbnÀ]mŠNjw0ak(X_Hy7js,\~Dyh.ck8hµnsÖ Ú¬×« Ö«ØÜޥܹ«º
Sj¡b|Ö{åyè¢O\]=d@`>c>r+SÊwzÓÖÕÓÑÏÎÍÌ}ŽKU°FR±AKÎWRémìuîrØh],E 7Iª>L®?K¯?KŽCL¶FLŽRVôœè{Ã[]Å_iÀZgÀ^sÃ]s¿[m8_x5ee#Us2c[Go)Wj Qm.dwI{`أݎ¥ÔªÔšÒ£Ô¢Û°¥Û7UOn¢d~Òä?N\:e>eA^<cCNfÃtxØÕÕÔÒÐÏÌÌ}ŽJU±FQ¬?KÆSQçmìvïsØi],D5Hª?M?L®@LµDNœLR°CLàîªÈ^`¹TcÀ[lÃ]lžXr=er'Y|6g`Ou2fh#Q`Df"Pu2eSœÙ©Ó¥Ñ¢Ò¢Ò£â°šë³©ìާÂ[b8YUsÅ},FZ=g>jBa=a;l$M°epÄ}|ÖÔÔÔÒÑÐÎ~Ì|°IV¯FRª>JÁRTæoìwîvÙk`-E8L¬@O°BP°@M¶FPÀNUºHOÞàr»PYŒVcÅYfÄZh
0Qo&RZCl(Zl*[h']|@qZBe#Iª[sŽ~ةج ÌÒ¡Øè¬¡í¹¬î¹ñœ¯ÚyusB5ZÂ~iA`=i@l"E^;`=B^ºpsÊ|ÒÔÓÔÔÑÑÐ~Î{±HR¯EP©?LÀRTænìxîu×la1J¡8K¯CR±ER±BO»LTÄUXÃOSÌnh×~n¿QXÆ[džRd|)OeFi&ReK_Gf Rz:pt:jXA»gnÙÃÑ¥¡Ó¢Ñßè첊î»ñÀ²ôÆ·ë'BdEžwl#IfAk Ej C_<_B®dnÆ}xÎÉ}É}Ì}Î~ÑÐÐÐ|Ï{±FRCOš=J¿PSæqëxíuÖlb1L¡<PCR³FR³DQŒLTÄQVÄRUÆUVÌg]Í]eŒ_v.Rh'YZFj%Ug!NcMdNl+^c'UZgÕÛ¥ÅÔŠ Ôà
çêí³Šîº«ñÀ°ôÇžñµŠ¬>NW?®i|u'KgDk$FdAb>t-RÀstÏÑÎÍÊ}Á}Á|Ä~É{Ì|Ðy°DOANª>KŸPUäsìzíwØk_0J :O®DS±ES³DQŒKQÈSUÎ^^·ZXšNY¿f~£AXl.`k2e[Co*X\Be!Oh%Z`!QE[Ì
Ø×€ÒŠ»ejÊhpÜéëíªí²£ï¹šóÁ°ï² §>PX<Vo:Yk%Jm&Ha@_APgÀtuÓ~ÑÐ}ÑÐÉ}Ã}À~Ÿ||¿z{Äzx¯DR¯FQ«>KœMRæ
qíyïzÙna1L¡;O¯DS±CP²BM¹HPÅTYÙrk€S\Bb§IWw._l-cu<n\Ja"OdJ_Fj+[s.OÊ|ÞšÕÑËceËchÂYb¢8MÂ[eæìí® ìšÌwtMZ¡8Jb=EcKcm%Hh Db@fG²frÈ}xÕ|Ñ|Ð{Î}Ï|Ë{É}ÈÃŒ}Žrz«BOª@N£9HžHOæ
nîvîxÚoa/F¡7I°BN±?J®<I¿ai×|nÞ{nœcf{,Nl/a{@vDz]Ok,\V@p4daDU=¶inÝ๫É)Aw<o>~1N.JÒZaßpsìñž§²`g,JuAu?c;
<\¢Xln%Ic>b?r*O¿rtÐzÒzÐyÑyÏzÏzÌyÉ|ÇÁ~»{~µv|ªBOŠ>M4F±DLænîyî{Úm_1Fš;K³BL²CM¢7G¯cjÜœ`by*Mj+^i([h*aR
XC\Gh%P\>XA9YÌܯ¢Ö©¯IU}?9T9^ß·¹²J\ÇMWÛdjíÛ2SFiWjg7^;8Z©bts+La=_?JaÆyvÒ{ÐzÏxÏxÏxÏyËxÅ{À}|žvz°qx·|}®EQš?M2F¯ALænï{ð|Ýqb¢6H±ALœJR:ILfÂy°vyk.^r8ng*]l0fy@x]h*YY=`A\=]AŸrwÛ€Ò¥Ç[bÖfmÊ`kÄWhÈrØØu{ÑW`Ø_gí§¡ÛÃfxœm9N|>aA}4X¯l|t+L_=fB¯dnÉzÐzÍxÌyÍ}ÌzÌxÆ}v¿xwžux¿zÔ⬫BO9K,B§;Häpï {ò¡ßta£4E°@J¿IOÄak·dz|:eb Ph*b
Uk0df(_{HSm5a[?]?U@IWÕÓš¶HRÕ`ißx}á~Þ{~Ü{ÞÜ~×clÙZeéèž°Û|Ñak¹JV,Bf=v,S¹wn#E`<o%GŒorÎ|Î
zÌyËzÊxÈyÆ}wŸyv·suÑæ³
èŽè³
:M2H&@¢8Hãoî{ñ |Þta¡3D®?NÀXl¶gVt9il+`OK~VEb$WzCwxHwJdaDWAi*OÄsuÛ²=PÅKTØ`gâwzçèçæà~~ÜkqÚZcæëÀ¶ßÛioÑYc3IlAp"IÄe<_;>VÃvtÐ|Í
{Ê|ÉzÇxÃ}y¿yw·stÒìºì¹
éŽéž/H,E#A5Gâpì{ï|ßsb4FªAQŸLWOy
Ex}9kl2iTi+\\DZDa"Jb>šYjw3PO; MZØ¢cm#BËPXÙ^cápræêéçáyvÝkmØ[`ãíÄ»Þ
ÜotÔ[d+Ek@lCÉ
d@e>«X_Ì{ÏyÌ{ÊyÆzÄ~xÁ|x¹tuÆxì¶ížìºëÀëÄ/K-KvB3Gâoê{îwßqa.E°Rlžb@jRo5is>z`r9h`IT=~.K~,Q»ow>Q_@ÂpsÄW<'BÇLTÙ]aákoå|{èéçÞom×`dÔV[ßv|ðÈ¿ÝÛlsÏY`qCr"Cg?Áyr-LfAÀnkÑyÑwÌ
yÉzÄyÂ|wœxv¹ssãª~ïží¹îÅîÊ¡ìÄ2K-Ht<-Bâoì|ðyás_1I®Lg²Vw7hF{p3ns?wao7i\HY?:V¥O\x.JV<¥[eÇq1K]<1FÄJRØ[_àfjãstä{yæ~ä{ÖbeØ^cØ]bÝmqòƹÜ|ÙjpžLY[?u%Df;µlx
?Wy/LËxnÐzÍ
wËvÈyÅyÂ}w»tsÌxïºïžïÄîÈìÈìÉ¥2I,D!>£;Lâqë}ð|àuf 9R©>N°Lj5gFwo;ql1jUa\Ek#DWD~=a[>x9UÚ `hX7d> :LÈKOÙX[àcgãqrãvvä~{ãzÙfjÐTX¿HQÑTZè ÛxxÕfk
.KZCx%Bk;¢]oI^LYÏrÎzËxÉyÆyÄ~vÂ{u¹rsá¢|ðºðÀîÇíÊ¡ìËŠìÊŠ/E,D
&A·R^ãwêyð}áxf3HŠ<M»Vop)]r3in4er6pTco3`K\YG|9^°m}¬\e±{}YBf"FeB§EUÌOUØX[Þ`eálmârtä{{ä}àywÝilá{yâå ÚtxÁYc\E_F0Ip>JbSeŒgdÐtÍzËxÇyÆyÃ~x¿zuŒuqë°~ðœ
ñÈîÈïË íÌ¥í˪)B&@#?µUbãxëyð|áye2DªBZŽXty1gv;ic'Ym/bv=r|F}\}3Uy/Q¶tÁ¥Xbh&Fd<p!?d<¢FXÊLSÙY[Þ`cáhjáijârrávuÝutÞzyꬡ鯊äÖnu8SZDf F
/Gr<6T®cnÎsdÏvË
zÈxÅzÃ}wÂ}wŸxqÂzqï·~ñÅñÉïÉîË¡íΫîÍ®x?#@#?³Saâ{ë}ð}âye5N¬Kd°Rmj([i+[d(]zDz{Awr9p
WDnÃÑ£«W`y>Vl@b:t#Ai<>RŸBLÙZZÝ]\áfgàjhËSVÎWYÔ]^ÑZ[Ú`a×imÎahÇcm_D]Cn#E1Gv!>r(LŸorÒyfÎxËxÇxÄyÃxÂ|vœvrÅ}pñœòÌñËïËîÍšíЮîÏm@z ?(D¶Xdãxì|ï|Üyv¬OjšD`§Nop/^ZJn2i[w@zKw?s³eÙºnn¢dj^B_;f<p @mA4Kš9HÏRSÕWYÜ`báomÝbbÖPWßR]âjzæ~ãx×nr9Q]A]>p A3Iz(DkFÌ~yÓ~nÍxÊyÉyÃxÁyÂ~wºurËrôÉñÍ ñÍ¡ïÎ¥ïЪïÏšðÌ£g>p:)CŽQ[â
uì}ï Þ|s,H¯Vr8^z@i_#Uj.fiWwC{akÎÇq`#KdE`AdBm!Bn B~/I+C»DKÊPTÖ[^ÜfiÞijÚ^aØZ]ÚXbÝ_mÛnw¿]c]A^Af@t"A3I+Em!HÑ|ÐsËxÉ{ÊyÄ
{ÁyŒ|xµrpËvöÑ£òТòÑ©ñÑšïËîÉïÉb=d=8L»T[àpì|ï~àyi-H¥Mm{3_m.X`&W]VihWSR}Ço/N[EgBaAc@g@o?n?x$@.@»DLÒW\ØcgÛimÝnràvxäãÚwx-HVBbDi@v$D6J
-Dq EÒËsÊ{Æ}Ç|Ã}œ|ž|xoqÈ{öÖšóÑ€óÐ¥ñÏ€ñÍ¡ñËòÉ_?\?4IŸVZáqë{î|ázf.G>[f$Sp3]e'WYRXo9qhh¥^D_\!K]Fo"Dd@bA`>k?l@p"Av=";¹DLÎY`×inÞvxåæãÌjncCY Kg$Gf?{,I:N0Fu$GÒÅvÆ{Ã~ÁÀ|¹~{ŽyxšmpÑö×§óÎôÑ€óÎ òÆíºÓt_@X={&B²LTárê{í{Ûte€YmVsa#Ql(Tf$QTKhw?t}I}^{šed1\YF{)Fc@_@b?b?l!Bm A(A0H©CT»S_Æai×ouÞ~~ßÛÈ{zn7YZ#Md!GaA|.J?T6L,LÐ|®^`Žefµor¹xwŒ|ž|{¯vw£fnä¶öÐôÌõÊðŸÊly.Ed=8ShAq>5GÞzlé{ë~ßI]}>_SEq-Wf%Sm+ZxEwWYV[Spb)Sy'Fg"F_Ca@a@hBkAz%B¹LWÍ[`Î_dÓhkÙnpØrrØtsàçŽèŒ§»wA^U?{-J=T3K3QË}užjjŽbd¬Zb€T^£W`€^f€ci\hîŸõÆôÉòÂÉpr#Bs"A5J§uUg/G}#>Útiêzì~Þyj°`ui+NP>}Aoh,_Cp`%XL|PtBybmMrGlm Dh"DaC_CbEfCw'Eq"CŽKUËX]Í^c×hjÙklØlnÜ|wâæ¯é¶îŸ€îì xl$E5N,F8UË|uÂ|vŸvt¹ps±ekŠWaJY¬YZDQí¹öÊôÇÇjx'B/G:L9K¡qXe{"?Úvkë|ìyãu·uYC\De$Nn,Ui)Wj/[k5ee+^p:qXy€S}Xyl/Vf#IeF^Gg#Hk#G7Lr!C¶LWÇW]ÕcgÚijÚkjÛqoàzâä¡ç¬ì·ñŠóÊŽ³m A})D>XÇzrÃy¿|wœyxžtv°lrŠdmŒgYÁg[ôÉ÷Îé²
2I;M>O§IT?Pu5V°°y#AÛxlí~í|änTkQ>_H]G[Iw;gYGe)Ys8kt;q}Le¢ww?hNjb@kA]Ai#Gh?®DO~$A±HUÕ_aÙceÛjhÜkjÝroàuá}ã
æ€ê²ïœ¡òDZôÑœTgl<CWÅyoÄtÁ|tœyvºww³ru®joÆp\ÜnöÐöÌÉ}e7M BRMW BQ£HZXA®¶m=Úxiì{ï|åiOdUC_GXCb$Tp6aaIb$Rf)[{EzzE{ekq5cYteAq%D_AeBo?µFM)BžKUØ]]ÜecÜhdÜkgÞsoßzrà
zâä æ®íŒ£ñƲóΜ۵©]6LXÅ|qÅrÂ|sŒxu·sr°oqŽgfã |ôÂøÒò¿®OP¢?O±NV€DQ¢DRK_O8Š}·m<Úwfí{î¡{æg?Z^HY?UBxBpf*Ta!KYCZIk1d|J~dqpzLnjAn!Be@cB1FÌVW0FŸNTÚaaÝfcÜfbÜhdÝpkÞwoàxáãå«ë¹£ïŲðÌ»ôÓ¿t6QªTXÆuÂ~tÀ{s»wrŽrpjlÇ|n÷Ï÷ÌøÑßhš@JªCNµOU@Q¢L[G]K
-6 uºs%BÙteë|è}ápBeWCZ@`!Le'Rg(Q`!KXC]Mh,Zl8mpOzNq}Bd=_~7Vh@n>²DMÐZ\0GÇTXÚbaÞjfÝfbÜd_ÜkeÝsmß~và|âäšè¶¢íÁ°ðÈžòÏ¿€qyµ_\Ãu¿|s»yqºxrŽsrjkÕt÷Ì÷ÍõÄÌfW°FL°HN©EO¡DSH[>VN
9dx¹z/I×qcìzì{ãoCbXA[Fe%N]Ka"KZI[H_"Qk3dtDycU
x?iaEh Bn$Db>)AÃPTÊZ\3LÒ^^ÝhfÞjfÞhdÛfbÜibÝpjÞzsßzáâ æ²êŸ®ïƶð˜Ԛ¿haŸ}tŸ}vœ|u»zu³tsµolÒ}dî²zøÏëªvÀQQ«CMŠAL;M¢HXCYD\M
8Vož
<QÔl_ëyìzãk PeYD` IWDa"Nb&P_ J[Fc&Sj2cl5dj9el4egcA_<]:e;¢:HÉVW®DP€BQÙdaÝjgàniàjdÝgaÜhbÝojÞwoß~tß|á
ä¬èºšîŶðËœñÌ»ºe_HR§\_³om¶xt¶zvÇ~pÍu_ÙkúÒßb¯DL¢>M4H FVBVFZ7NL6Lg£IZÏg]éxí{æjFc^GW@_ K_!M_"Mc"JXB[Kj5jcv<mz?hf$J];Z:Z8(@ŸMOÅRR(DÇYZÛdaÞjgàlfàleßhaÜf^ÜkbÞrjÞ{oßxàã€æ¶€ìÂŽïÊ»óÏ¿Žps;L6H4G7KGVÀtgÓfç©}öĺTM,C7IASBVDXG]q#A~/GUiÇ©¢\fÌg^èxì¡zÝkEbYD]F\E[Hb#Me$NVBZD^JuDtkO{Z=X:U9i:€<HÇRQ.B¢@MØc\ÜgbÞidßkgàmhàkbÝg`Üi`ÜmdÝwkßsà|ãå¯éŸ®íǹñÌŸÒIU LU<Ns'DV;¬d^é¬róœÖc$@,D;QFX9PMa>Un!?BV¡kyÄš€¢mpÊf^éyí£zÔ|iCaXC[D]FYEb%Pc(S_"Md&Re'Th,\Mzu>fW>V;X8.B®BH*@5FÑZWÙc]ÝhaÞjdßjeàmfàngßkdÜkdÜjaÝrgÞ{nßzáãŠæ·šëĶïÊŒìIJCQ¡PWIT<O|.H·g`ó¿Ð^*A{&A3KHZ3LAXQg9Qr(Fr,IVlŸ¡šuwÈd\ézï€}Üoq*PWC_I^H`$Oj.Zf(Y|Cpe*V_'Tn3eYr8bT>W;c7z#<.DºIOÍXWÓ]Y×b\Ûf_ÞhaßkeànfàsjßohÝmeÝlbÜodÝxlÞwáâ ä° è¿±íÈœðÍŒ¢\cJTQZN\¢Q[¹\\Ârb7K1F3KM^4J1KViNdt*Fm#Cc Bz<[Ê«ŠŸÇe^ëzð€Ìzme"KYD_Ic#Oa&Rm2_] R
Qc)Yl5_r7br;lr:fS<d7->¹GJÇQOÏYVÓ\WÕ_XØ`ZÜe]Ýg`ßiaßkeàpiàrkßrjßqgÝriÞxkÞ~qà}áâšå·©ëÄ·ìÊ»ž~~DQT^¥]eµZZ¶QUªHS¯MU;NCX4J1HM` ]o;Sj!@j=]=n.RØ·«Ò«Çg`êxî¢~ÇunbGZCe%Oo*Tj*Xv>ij(Yv:iw?nt=hg%Qg(Uy@no,R'<³@DÇNMÍVRÑ[UÒ\V×_XÙ`XÝd\Ýd\ßhbàjeáphàpiàsiáwkßvjßznàsá}à
á£ä³£èŸ±ìǺ֊CULWª[`Ä`ZÂXUÍ`XžOR>R
;V;RDX¬gsG\f>i!@9K
\ No newline at end of file
+âyá
tßlÞnâpéwêtÍde¡ÿW¬ÿY°ÿV²ÿV±ÿUºÿXÄÿZËÿ\Íÿ`ÍÿbÌÿ_ÍÿaÐÿbÓÿaÐÿaÏÿcÐÿcÎgeÌggÌÿ`ËÿcÎÿ_ÐÿaÏÿaÍÿcÌÿaÊÿbÊÿaÊÿbÈÿa¿ÿa±ÿYÁÿZØzoÝqÜ~jÝnÞmÞhÞgÝjÝnç¢zùÿ鎩ÿZžÿ]Œÿ]»ÿbÁÿ]Âÿ_Âÿ^ÃÿbÃÿ^¿ÿ^ÇniâmâlâkàiånêréjÌÿZ¢ÿPÿR³ÿS²ÿQ²ÿPºÿVÄÿ\ÊÿZÍÿ[Íÿ_Ïÿ_Ïÿ]Ðÿ`Óÿ_Ñÿ_ÑÿaÐÿaÐÿaÏÿaÎÿ^Íÿ`Îÿ\ÐÿaÏÿ_Îÿ_Íÿ`Ëÿ^Ëÿ_Ëÿ_Êÿ_Âÿ`¶ÿZ²ÿYÑnkßsàoá
mâ
láiàhÞiÛkÛmõÃúÿÄtg³ÿY»ÿ]Ÿÿ]¿ÿ]Áÿ]Äÿ]Æÿ^Éÿ`¡ÿR_ÿAámãkâlánæqçoåkÌÿ_¡ÿN¯ÿNŽÿR±ÿP²ÿNŒÿTÄÿYÊÿYÎÿ]Ïÿ]Ðÿ_Ïÿ`Ñÿ^Òÿ`Òÿ`Òÿ^ÒÿaÑÿ`ÐÿaÏÿaÎÿ`Îÿ]ÑÿdÏÿbÎÿaÍÿ^Íÿ_Ìÿ]Íÿ_Íÿ^ÃÿaŒÿ\°ÿXÃÿdÛ~sâvãqäpâ
mâlÞjÛ~lÙ}kåuúÿÿY¹ÿ[¿ÿ\¿ÿ^ÀÿaÆÿbÏÿbÿP[ÿB]ÿ?âmå
lã
oårçrâoæ
jÎÿW¡ÿJ®ÿN³ÿR±ÿPŽÿP»ÿRÅÿXÉÿZÍÿ[Íÿ]Ïÿ^ÎÿaÑÿ^Ñÿ_Óÿ]ÑÿaÒÿcÐÿZÎÿWÎÿ\Ìÿ[Ëÿ\Îÿ`ÏÿbÏÿbÌÿ]Ìÿ^Ìÿ\Íÿ\Íÿ^Åÿ`Ÿÿ]ŽÿXÁ\fÙzuâwâtáoâjálßmÝnÚ~lØzióŒûÿ ÒpŽÿWŸÿ\Àÿ\Àÿ_ÉÿbÿO\ÿB\ÿ<dÿ?ã
nänæséqçlãlæ
iÎÿU¡ÿJÿO²ÿP°ÿO²ÿP»ÿTÄÿXÇÿZËÿ[Íÿ]Îÿ[Îÿ_Òÿ^Ïÿ`ÐÿcÑÿ^Òÿ`ÐÿZÊÿYÊÿXÊÿYÇÿYËÿ_ÌÿcÍceÌÿ_Îÿ^Ìÿ]Íÿ]Íÿ]Éÿ_Àÿ\·ÿYÂÿbÖspÞtà
tß
oàlànànßmÜ~nØyißjùÿ÷ÿžÿbºÿWÀÿ]ÆÿbÿOZÿBaÿEdÿ@bÿ>äpåpèpæfçhånçjÌÿVÿJÿO³ÿP±ÿO²ÿNŒÿTÆÿWÇÿYËÿYËÿ]Îÿ\Ðÿ`Ðÿ^Ðÿ_ÑÿaÑÿ^Ñÿ_Ðÿ^ÌÿcÈikÈqqÅmlÆÿ^Èÿ^Ëÿ`Ìÿ`ÍÿcÎÿ`Íÿ]Îÿ\Èÿ]¿ÿ\¹ÿZÂÿ_ÔolÚyqÝtßoßnàkálß}jÚxiÙueÖÿaðŽúÿ§á€~°ÿV»ÿ]ÿNZÿ>^ÿBeÿD`ÿ?]ÿ<æoéqåeÞÿ[ågæoèkÐÿVÿH¬ÿM³ÿQ±ÿN·ÿNÀÿTÊÿWËÿXÎÿYÎÿ\Ñÿ^Óÿ_Òÿ^Ðÿ^Òÿ^ÍbhÈu}Ã{ÈÍÒŠÐ¥ÓªÏÆssÄÿ\ÉÿdÍÿcÍÿ_Ìÿ]Èÿ\¿ÿ[·ÿYÀÿ]Öni×tmÚyqÞqÞ}mß}jà{gÝveØre×ÿbÖÿbÝjøÿûÿ¥ÉwhÿMXÿ>]ÿ?cÿCaÿB]ÿ=_ÿ;épêm×ÿVÑÿVçjémêkÑÿVÿG¥ÿMÿN°ÿLŽÿOŸÿTÇÿUÉÿYÍÿXÍÿZÑÿ\Ðÿ^ÏcfÈntÀbm¿kuÁpvÆz}ÈÌÏÒ¥Ö¬Ù² Þ¹šÑŸ_hÄÿ`Çÿ^Èÿ\ÂÿYŒÿWŽÿUÃÿ[ÙoiÚtkÚvoÛyrÞ{lÜueÜÿcÛÿcÙÿcØÿaÙÿ`×ÿaë¡}ýÿ¬Ý€Wÿ>Zÿ?dÿBaÿA^ÿA]ÿ?`ÿ;ísäÿc®ÿIÊÿTèiêmêjÑÿSÿE ÿKªÿO¬ÿO°ÿQžÿRÂÿUÄÿVÈÿZÌÿ[ÏÿYÐÿ]Œÿ\œÿb»]f¿ioœiqÂnsÃx|Ê
Òէ׬۳¡Ý¶€ÝŒ¬Ø³Šœos¶ÿWŸÿX¿ÿYžÿY²ÿTÁÿ[ÝqjßxlÙsmÖplÚtkÛsgÜÿbÝÿdÚÿcÙÿdÚreÚsfÜzkó¹~ÿLVÿ>bÿAdÿB^ÿ@^ÿ@`ÿ?Xÿ9ëoÌÿTÿFÊÿVêjëqégÎÿTÿD¢ÿMªÿS¬ÿQ®ÿP¶ÿTÀÿXÂÿVÈÿXËÿYÒÿ[ÆÿY»ÿVœÿ\ÁÿdÁchÄjmÃlqÅsvÉ~Ïקگ܎£Þ¹©Ü¹§Ú»°àĹʪÿWŽÿV²ÿU¯ÿVŸÿ]ßumä~oÞvlËÿ`Ëÿ_ÝujßÿdßseÜÿcÜqeÝsfßviázjÿIWÿ=`ÿ?dÿ>^ÿ>`ÿC_ÿDdÿFÿUàÿ`šÿJÿHÊÿWéiëoèiÍÿSÿF€ÿM¬ÿPÿR¯ÿR¶ÿTÀÿUÄÿXÉÿYÊÿYËÿX»ÿSœÿ\Ÿÿ_ŸÿaŸÿdÄhlÆknÆprÌxxÓکܯ ثَ¬à·åÿ¿æÿŸëÿÅÉ¡ÿMªÿS§ÿT»ÿ[Þsjä}láynÁÿYÿJÓffßshàreÝpeÞqgßqfäxk€ÿSWÿ;`ÿ?dÿA]ÿ>cÿ@\ÿDmÿRÿXÏ}u¿ÿMÿJÿGÉÿWç
jëpè
hÌÿSÿH£ÿO¬ÿQÿQ¯ÿQ·ÿRÀÿVÅÿWÉÿYÉÿY»ÿSºÿYŸÿ\¹ÿ\»ÿ`ÃbfÉlmËppÍssÍwvÔ×Ó Þº±åÿœâŹâÄžãÿŒåÿÁëÿʱqwÿKÿPºÿXßtlå}názpÄÿ`nÿ=±ÿVÝqjàrgÝoeßqhâshÎÿ`^ÿA_ÿ?gÿA^ÿ?cÿA]ÿ@fÿMCeÄwxË|uÿJ£ÿJ ÿJÇÿUçjétè
lËÿWÿF£ÿM«ÿQ¬ÿO°ÿP·ÿQÁÿVÄÿWÊÿ[ÀÿXŒÿX»ÿXœÿ[Œÿ_ÂafÆhlËnoÍqpÉmoÌssÎ~Ò໯âÀ³á¿ŽÞŒ²áÄžâÄžâÿœäÿÀæÿĶÿD¶ÿTÞtkä}pâ|rÆÿ\hÿ>~ÿBÍÿ_ásgÝÿcàqiãtizÿCYÿ<iÿCdÿ@bÿ@`ÿ@bÿFwÿYŸqxÉ~zÕ~ ÿK¢ÿLÿKÆÿXålèrç
nËÿYÿJ¡ÿL«ÿOÿQ®ÿP·ÿRÀÿW¿ÿWÒÿbŽÿPºÿVœÿVŸÿ[ÁÿaÈglÌooÊmoËmpÁcjÃrw؀ീ޵§Û³šÞ¹¯âÞãÄ¹âÆºâǺáÿŒäÿÁéÿÇXhÿNÝqgä}oâ{rÇÿ^nÿ?_ÿ7ÿFÔÿdÚtjáti§ÿRYÿ=dÿ?gÿA`ÿAaÿAbÿAdÿJ·kwÄvwÑ~ÕÿMÿKÿGÃÿVælèrç
oËÿZÿHÿK©ÿM©ÿOÿTµÿTœÿT¿ÿ\Özi³ÿTŒÿVŸÿVÁÿ]ÈaeËilÊijÉijº[fÅx}ݚܧ۪۫à¹ß»¯àŸ³ÞÀ·ßžßùáÿœáÿÀåÿÅל³ÿLÛphã|mã|qÆÿ^lÿ@Xÿ8MfÞœ°åÿŸæÅ·_ÿF]ÿBgÿCdÿDbÿBcÿB]ÿ@¢XnÈxyÏÔ~Ô{ÿL¥ÿL€ÿIÄÿTæjêrè
mÊÿVÿEÿJ¬ÿN¯ÿM°ÿN¶ÿQœÿUÑ{oÐÿ_°ÿSŒÿUŸÿWÅÿbÅÿbÂÿdÉÿdœÿ_ÏÜØÙ¡Ú€Ý±¥Ü±ŠÝŽªÜµ¬àŒ³á¿ŽàÀµÞÞàÿŸßÿÀåÿɵpvØnfånâ}nÀÿY\ÿ<rÙ·«æÿ¿êÿÂðÿÉxIf]ÿAeÿA`ÿ>]ÿ?dÿCÿ\Ë{|Í}Õ}Ô}Ó{©ÿM¬ÿN¬ÿKÇÿSåkêsênÌÿYÿE¢ÿK¯ÿN³ÿNŽÿN»ÿQŸÿSàyÈÿW¯ÿQ·ÿUÁÿYÄÿ^ÄÿdÈbfŸÿaÓ~y×ÖÛÜ¥Û§Ú©Ø£Û«¡Þީ߹¯ßŒ±Þœ°Ù²©ÝÀ·ÞĺÞÅŒÜÅ¿Ûwå}eÞÿd¶^eÀÛ»°åÿŒãÆžâÆºïÿÈ~Mf_ÿCaÿ?_ÿ=dÿ?_ÿCÂq{Í~~Ö~Ô|Ó|Ó{ÿOÿM®ÿLÎÿRækërìqÏÿXÿD£ÿL¯ÿN±ÿM²ÿKžÿNµÿPç{ÈÿW³ÿTŽÿR»ÿVÄÿ^Åÿ_ÀÿdÒvsÓ|xÍ{{ØÚØÚ¢×ڡ܊ۚܯ¥Ü±š×©Ø²šÛŒ³Üº²Ú»Ž×¹²Ý±Šâ}iÝß»ªÞÀ³âǹàöâÄ·æÿÀîÿÆiÿV_ÿC_ÿ>^ÿ=fÿBKeÐ|}ÔÕ~Ô{Ò|ÒzÿO¬ÿM°ÿKËÿSèkîsîsÑÿXÿC¥ÿI®ÿL¯ÿL¯ÿLµÿM±ÿNôŽ
Õÿ]ºÿS·ÿTŸÿVÅÿ^ÃÿbÑstÒtrËpqÔ~}ÕØØ×ÛÛÙÚ€Ú© Ù§Ø®§Ø³«Ù®ŠÖ©£ÕŠÏ¥¡×Žªßµ€ßŒ¬ãÃŽá¶ßÀ³âĹߺ®åÿœäÿºWÿA`ÿA\ÿ>cÿ@ÿYÍv|ÐÖÕÓ~Ò|Ñ{ªÿNªÿM¬ÿKÈÿTèjítìsÐÿYÿG¥ÿK¯ÿN¯ÿL°ÿK³ÿM²ÿPõŽßzeÏÿX¶ÿQ»ÿWŸÿ]ÐkmÏqqÇhkÔzwÑyzÑ{|Õ
ÚÚÚÛØ××ـة¢×¥×€¡ÓÑٮܶšáÀ²àŸ°ÞŸ²ßÀŽá÷໮ÔÚ©³Yÿ@_ÿ?]ÿ<fÿJ¯]pÐ|}Ô×ÕÓ~Ó}Ô{šÿM§ÿJªÿLÌÿWèkëuìqÑÿZÿG¥ÿLÿM®ÿK¯ÿK±ÿK±ÿTô¯{ågØÿ]ºÿSºÿWÏjlÊgjÃbiÓrqÎpqÍvwÓz{××
ÖרÔ
ÕØØÖÔÏסݮບߌ«Ýž¬Ý»¯àÁ¶àÞäÿŒÔÎØzÿ]\ÿ?\ÿ?aÿAÿbÏ{|ÑÔÓ~ÒÒ}Ò|Ò|ªÿN©ÿN³ÿMÑÿWékìtípÒÿ\ÿC¢ÿL¬ÿMÿK¯ÿK¯ÿI³ÿW÷ºémáÿ`ÈÿVÉÿcÇciÁ_hÑmnËjmÈiqÎruÓx|¿k}µd~¯fŸvžn~ÏÍÏŒvÆÏÜ¥àŽ€áº§ÚŽ¥Û¹®ÞŸ±á¶âùãǻ޶©»oo±\fÒ§Tÿ<^ÿAbÿCeÿJ»huÐ||ÕÔ~Ò}Ò}Ñ{Ð|Ð
{¬ÿPªÿP·ÿNÖÿVêkítîqÕÿ[ÿD¡ÿJ¬ÿM°ÿM±ÿK²ÿH°ÿOøÀð¢sÙÿXÈÿYÀÿ_ºÿdÏikÈeiÆcjÉgmÏouŸez¶`y¢Mo
>p²tQ~Dy?nhÿQ_ÿSŠl|Ø á¶Šß¹©Þº«Úž«ÞŸ±àÀ³ãĶ߻®ÆšÿW£ÿWÖÿb\ÿ>\ÿ>aÿ?~ÿYÍy|ÒÔÔÒÐÏ|Î
|Ðy°ÿR®ÿMžÿNÖÿUélìsíqÔÿZÿE£ÿJ¬ÿK¯ÿL°ÿL°ÿI¥ÿGò¹ó©xÒÿ`Íhgµÿ]ÍeiÅbjÆ`hÇdlÎinŒ\rº]wHu}ÿdmÿYN}=t}AtgÿbRÿHŠjtÓݰݷ©ÜހܶšÚž«ÝŒ±Þ»Æ¡ÿT£ÿVÀjmÝÿZ]ÿ>aÿ>`ÿ?_ÿH¯`pÍ~}ÕÕÓÑÏÐ}Î}Î}²ÿU°ÿQ¶ÿKÓÿVékësípÖÿ[ÿE¢ÿJ«ÿL®ÿLÿL±ÿJªÿIØwöŽÜoÅÿ_É`hÄ^fÂ[gÄ^hÃbnÀ]mŠNjwÿakÿX_ÿHy7jsÿ\~Dyhÿck8hµnsÖ Ú¬×« Ö«ØÜޥܹ«º
Sj¡b|Ö{åyè¢ÿ\]ÿ=dÿ@`ÿ>cÿ>rÿSÊwzÓÖÕÓÑÏÎÍÌ}ŽÿU°ÿR±ÿKÎÿRémìuîrØÿ]ÿE ÿIªÿL®ÿK¯ÿKŽÿL¶ÿLŽÿVôœè{Ãÿ]Å_iÀZgÀ^sÃ]s¿[mÿ_x5eeÿUsÿc[ÿGoÿWjÿQmÿdwI{`أݎ¥ÔªÔšÒ£Ô¢Û°¥ÛÿUOn¢d~ÒäÿN\ÿ:eÿ>eÿA^ÿ<cÿCNfÃtxØÕÕÔÒÐÏÌÌ}ŽÿU±ÿQ¬ÿKÆÿQçmìvïsØÿ]ÿDÿHªÿMÿL®ÿLµÿNœÿR°ÿLàîªÈÿ`¹ÿcÀ[lÃ]lžXr=erÿY|6g`ÿOu2fhÿQ`ÿDfÿPu2eSœÙ©Ó¥Ñ¢Ò¢Ò£â°šë³©ìާÂÿbÿYUsÅ}ÿFZÿ=gÿ>jÿBaÿ=aÿ;lÿM°epÄ}|ÖÔÔÔÒÑÐÎ~Ì|°ÿV¯ÿRªÿJÁÿTæoìwîvÙÿ`ÿEÿL¬ÿO°ÿP°ÿM¶ÿPÀÿUºÿOÞàr»ÿYŒÿcÅYfÄZh
ÿQoÿRZÿClÿZlÿ[hÿ]|@qZÿBeÿIª[sŽ~ةج ÌÒ¡Øè¬¡í¹¬î¹ñœ¯ÚyusÿBÿZÂ~iÿA`ÿ=iÿ@lÿE^ÿ;`ÿ=ÿ^ºpsÊ|ÒÔÓÔÔÑÑÐ~Î{±ÿR¯ÿP©ÿLÀÿTænìxîu×ÿaÿJ¡ÿK¯ÿR±ÿR±ÿO»ÿTÄÿXÃÿSÌnh×~n¿ÿXÆÿdžÿd|ÿOeÿFiÿReÿK_ÿGfÿRz:pt:jXÿA»gnÙÃÑ¥¡Ó¢Ñßè첊î»ñÀ²ôÆ·ëÿBdÿEžwlÿIfÿAkÿEjÿC_ÿ<_ÿB®dnÆ}xÎÉ}É}Ì}Î~ÑÐÐÐ|Ï{±ÿRÿOšÿJ¿ÿSæqëxíuÖÿbÿL¡ÿPÿR³ÿR³ÿQŒÿTÄÿVÄÿUÆÿVÌÿ]Í]eŒ_vÿRhÿYZÿFjÿUgÿNcÿMdÿNlÿ^cÿUZgÕÛ¥ÅÔŠ Ôà
çêí³Šîº«ñÀ°ôÇžñµŠ¬ÿNWÿ?®i|uÿKgÿDkÿFdÿAbÿ>tÿRÀstÏÑÎÍÊ}Á}Á|Ä~É{Ì|Ðy°ÿOÿNªÿKŸÿUäsìzíwØÿ_ÿJ ÿO®ÿS±ÿS³ÿQŒÿQÈÿUÎÿ^·ÿXšÿY¿f~£ÿXlÿ`k2e[ÿCoÿX\ÿBeÿOhÿZ`ÿQÿ[Ì
Ø×€ÒŠ»ejÊhpÜéëíªí²£ï¹šóÁ°ï² §ÿPXÿ<VoÿYkÿJmÿHaÿ@_ÿAPgÀtuÓ~ÑÐ}ÑÐÉ}Ã}À~Ÿ||¿z{Äzx¯ÿR¯ÿQ«ÿKœÿRæ
qíyïzÙÿaÿL¡ÿO¯ÿS±ÿP²ÿM¹ÿPÅÿYÙrk€ÿ\ÿb§ÿWwÿ_lÿcu<n\ÿJaÿOdÿJ_ÿFjÿ[sÿOÊ|ÞšÕÑËceËchÂÿb¢ÿMÂ[eæìí® ìšÌwtÿZ¡ÿJbÿ=ÿcÿcmÿHhÿDbÿ@fÿG²frÈ}xÕ|Ñ|Ð{Î}Ï|Ë{É}ÈÃŒ}Žrz«ÿOªÿN£ÿHžÿOæ
nîvîxÚÿaÿF¡ÿI°ÿN±ÿJ®ÿI¿ai×|nÞ{nœcf{ÿNlÿa{@vDz]ÿOkÿ\Vÿ@pÿdaÿDUÿ=¶inÝ๫ÉÿAwÿ<oÿ>~ÿNÿJÒÿaßpsìñž§²`gÿJuÿAuÿ?cÿ;
ÿ\¢XlnÿIcÿ>bÿ?rÿO¿rtÐzÒzÐyÑyÏzÏzÌyÉ|ÇÁ~»{~µv|ªÿOŠÿMÿF±ÿLænîyî{Úÿ_ÿFšÿK³ÿL²ÿM¢ÿG¯cjÜœÿbyÿMjÿ^iÿ[hÿaR
XÿC\ÿGhÿP\ÿ>XÿAÿYÌܯ¢Ö©¯ÿU}ÿ?ÿTÿ^ß·¹²ÿ\ÇÿWÛdjíÛÿSFiWjgÿ7^ÿ;ÿZ©btsÿLaÿ=_ÿ?ÿaÆyvÒ{ÐzÏxÏxÏxÏyËxÅ{À}|žvz°qx·|}®ÿQšÿMÿF¯ÿLænï{ð|Ýÿb¢ÿH±ÿLœÿRÿILfÂy°vykÿ^r8ngÿ]l0fy@x]hÿYYÿ=`ÿA\ÿ=]ÿAŸrwÛ€Ò¥ÇÿbÖfmÊ`kÄWhÈrØØu{Ñÿ`Ø_gí§¡ÛÃfxœmÿN|ÿ>aÿA}ÿX¯l|tÿL_ÿ=fÿB¯dnÉzÐzÍxÌyÍ}ÌzÌxÆ}v¿xwžux¿zÔ⬫ÿOÿKÿB§ÿHäpï {ò¡ßÿa£ÿE°ÿJ¿ÿOÄak·dz|:ebÿPhÿb
Ukÿdfÿ_{HSmÿa[ÿ?]ÿ?Uÿ@ÿWÕÓš¶ÿRÕ`ißx}á~Þ{~Ü{ÞÜ~×clÙZeéèž°Û|Ñak¹ÿVÿBfÿ=vÿS¹wnÿE`ÿ<oÿGŒorÎ|Î
zÌyËzÊxÈyÆ}wŸyv·suÑæ³
èŽè³
ÿMÿHÿ@¢ÿHãoî{ñ |Þÿa¡ÿD®ÿNÀXl¶gVt9ilÿ`OK~VÿEbÿWzCwxHwÿdaÿDWÿAiÿOÄsuÛ²ÿPÅÿTØ`gâwzçèçæà~~ÜkqÚÿcæëÀ¶ßÛioÑÿcÿIlÿApÿIÄeÿ<_ÿ;ÿVÃvtÐ|Í
{Ê|ÉzÇxÃ}y¿yw·stÒìºì¹
éŽéžÿHÿEÿAÿGâpì{ï|ßÿbÿFªÿQŸÿWOy
Ex}9kl2iTiÿ\\ÿDZÿDaÿJbÿ>šYjwÿPOÿ; ÿZØ¢cmÿBËÿXÙÿcápræêéçáyvÝkmØÿ`ãíÄ»Þ
ÜotÔÿdÿEkÿ@lÿCÉ
dÿ@eÿ>«ÿ_Ì{ÏyÌ{ÊyÆzÄ~xÁ|x¹tuÆxì¶ížìºëÀëÄÿKÿKvÿBÿGâoê{îwßÿaÿE°Rlžb@jRo5is>z`r9h`ÿITÿ=~ÿK~ÿQ»owÿQ_ÿ@ÂpsÄWÿ<ÿBÇÿTÙÿaákoå|{èéçÞom×ÿdÔÿ[ßv|ðÿ¿ÝÛlsÏÿ`qÿCrÿCgÿ?ÁyrÿLfÿAÀnkÑyÑwÌ
yÉzÄyÂ|wœxv¹ssãª~ïží¹îÅîÿ¡ìÄÿKÿHtÿ<ÿBâoì|ðyáÿ_ÿI®Lg²Vw7hF{p3ns?wao7i\ÿHYÿ?ÿV¥ÿ\xÿJVÿ<¥[eÇqÿK]ÿ<ÿFÄÿRØÿ_àfjãstä{yæ~ä{ÖbeØÿcØÿbÝmqòƹÜ|ÙjpžÿY[ÿ?uÿDfÿ;µlx
ÿWyÿLËxnÐzÍ
wËvÈyÅyÂ}w»tsÌxïºïžïÄîÿìÿìÿ¥ÿIÿDÿ>£ÿLâqë}ð|àuf ÿR©ÿN°Lj5gFwo;ql1jUa\ÿEkÿDWÿD~ÿa[ÿ>xÿUÚ `hXÿ7dÿ> ÿLÈÿOÙÿ[àcgãqrãvvä~{ãzÙfjÐÿX¿ÿQÑÿZè ÛxxÕfk
ÿKZÿCxÿBkÿ;¢]oÿ^ÿYÏrÎzËxÉyÆyÄ~vÂ{u¹rsá¢|ðºðÀîÇíÿ¡ìÿŠìÿŠÿEÿD
ÿA·ÿ^ãwêyð}áxfÿHŠÿM»Vopÿ]r3in4er6pTcoÿ`ÿ\YÿG|ÿ^°m}¬\e±{}YÿBfÿFeÿB§ÿUÌÿUØÿ[Þ`eálmârtä{{ä}àywÝilá{yâå ÚtxÁÿc\ÿE_ÿFÿIpÿ>ÿbSeŒÿdÐtÍzËxÇyÆyÃ~x¿zuŒuqë°~ðœ
ñÿîÿïÿ íÿ¥íÿªÿBÿ@ÿ?µÿbãxëyð|áyeÿDªÿZŽXty1gv;icÿYmÿbv=r|F}\}ÿUyÿQ¶tÁ¥ÿbhÿFdÿ<pÿ?dÿ<¢ÿXÊÿSÙÿ[ÞÿcáhjáijârrávuÝutÞzyꬡ鯊äÖnuÿSZÿDfÿF
ÿGrÿ<ÿT®cnÎÿdÏvË
zÈxÅzÃ}wÂ}wŸxqÂzqï·~ñÅñÿïÿîÿ¡íÿ«îÿ®xÿ?ÿ@ÿ?³ÿaâ{ë}ð}âyeÿN¬ÿd°Rmjÿ[iÿ[dÿ]zDz{Awr9p
WDnÃÑ£«ÿ`yÿVlÿ@bÿ:tÿAiÿ<ÿRŸÿLÙÿZÝÿ\áfgàjhËÿVÎÿYÔÿ^Ñÿ[Úÿa×imÎahÇcm_ÿD]ÿCnÿEÿGvÿ>rÿLŸorÒyfÎxËxÇxÄyÃxÂ|vœvrÅ}pñœòÿñÿïÿîÿšíÿ®îÿmÿ@zÿ?ÿD¶ÿdãxì|ï|Üyv¬Ojšÿ`§Nopÿ^ZÿJn2i[w@zKw?s³eÙºnn¢dj^ÿB_ÿ;fÿ<pÿ@mÿAÿKšÿHÏÿSÕÿYÜÿbáomÝÿbÖÿWßÿ]âjzæ~ãx×nrÿQ]ÿA]ÿ>pÿAÿIzÿDkÿFÌ~yÓ~nÍxÊyÉyÃxÁyÂ~wºurËrôÿñÿ ñÿ¡ïÿ¥ïÿªïÿšðÿ£gÿ>pÿ:ÿCŽÿ[â
uì}ï Þ|sÿH¯Vrÿ^z@i_ÿUj.fiWwC{akÎÇq`ÿKdÿE`ÿAdÿBmÿBnÿB~ÿIÿC»ÿKÊÿTÖÿ^ÜfiÞijÚÿaØÿ]ÚÿbÝ_mÛnw¿ÿc]ÿA^ÿAfÿ@tÿAÿIÿEmÿHÑ|ÐsËxÉ{ÊyÄ
{ÁyŒ|xµrpËvöÿ£òÿ¢òÿ©ñÿšïÿîÿïÿbÿ=dÿ=ÿL»ÿ[àpì|ï~àyiÿH¥Mm{ÿ_mÿX`ÿW]ÿVihWSR}ÇoÿN[ÿEgÿBaÿAcÿ@gÿ@oÿ?nÿ?xÿ@ÿ@»ÿLÒÿ\ØcgÛimÝnràvxäãÚwxÿHVÿBbÿDiÿ@vÿDÿJ
ÿDqÿEÒËsÊ{Æ}Ç|Ã}œ|ž|xoqÈ{öÿšóÿ€óÿ¥ñÿ€ñÿ¡ñÿòÿ_ÿ?\ÿ?ÿIŸÿZáqë{î|ázfÿGÿ[fÿSpÿ]eÿWYÿRXo9qhh¥^ÿ_\ÿK]ÿFoÿDdÿ@bÿA`ÿ>kÿ?lÿ@pÿAvÿ=ÿ;¹ÿLÎÿ`×inÞvxåæãÌjncÿCYÿKgÿGfÿ?{ÿIÿNÿFuÿGÒÅvÆ{Ã~ÁÀ|¹~{ŽyxšmpÑöÿ§óÿôÿ€óÿ òÆíºÓt_ÿ@Xÿ={ÿB²ÿTárê{í{Ûte€YmVsaÿQlÿTfÿQTÿKhw?t}I}^{šedÿ\YÿF{ÿFcÿ@_ÿ@bÿ?bÿ?lÿBmÿAÿAÿH©ÿT»ÿ_Æai×ouÞ~~ßÛÈ{znÿYZÿMdÿGaÿA|ÿJÿTÿLÿLÐ|®ÿ`Žefµor¹xwŒ|ž|{¯vw£fnä¶öÿôÿõÿðŸÊlyÿEdÿ=ÿShÿAqÿ>ÿGÞzlé{ë~ßÿ]}ÿ_SÿEqÿWfÿSmÿZxEwWYV[SpbÿSyÿFgÿF_ÿCaÿ@aÿ@hÿBkÿAzÿB¹ÿWÍÿ`ÎÿdÓhkÙnpØrrØtsàçŽèŒ§»wÿ^Uÿ?{ÿJÿTÿKÿQË}užjjŽÿd¬ÿb€ÿ^£ÿ`€^f€ci\hîŸõÆôÿòÂÉprÿBsÿAÿJ§uUgÿG}ÿ>Útiêzì~Þyj°`uiÿNPÿ>}Aohÿ_Cp`ÿXL|PtBybmMrGlmÿDhÿDaÿC_ÿCbÿEfÿCwÿEqÿCŽÿUËÿ]Íÿc×hjÙklØlnÜ|wâæ¯é¶îŸ€îì xlÿEÿNÿFÿUË|uÂ|vŸvt¹ps±ekŠÿaÿY¬ÿZÿQí¹öÿôÇÇjxÿBÿGÿLÿK¡qXe{ÿ?Úvkë|ìyãu·uYÿC\ÿDeÿNnÿUiÿWjÿ[k5eeÿ^p:qXy€S}XylÿVfÿIeÿF^ÿGgÿHkÿGÿLrÿC¶ÿWÇÿ]ÕcgÚijÚkjÛqoàzâä¡ç¬ì·ñŠóÿ޳mÿA}ÿDÿXÇzrÃy¿|wœyxžtv°lrŠdmŒÿYÁÿ[ôÿ÷ÿé²
ÿIÿMÿO§ÿTÿPuÿV°°yÿAÛxlí~í|änTkQÿ>_ÿH]ÿG[ÿIw;gYÿGeÿYs8kt;q}Le¢ww?hNjbÿ@kÿA]ÿAiÿGhÿ?®ÿO~ÿA±ÿUÕÿaÙceÛjhÜkjÝroàuá}ã
æ€ê²ïœ¡òDZôÿœTglÿ<ÿWÅyoÄtÁ|tœyvºww³ru®joÆÿ\ÜnöÿöÿÉ}eÿM ÿRÿW ÿQ£ÿZXÿA®¶mÿ=Úxiì{ï|åiÿdUÿC_ÿGXÿCbÿTpÿaaÿIbÿRfÿ[{EzzE{ekqÿcYteÿAqÿD_ÿAeÿBoÿ?µÿMÿBžÿUØÿ]ÜÿcÜÿdÜkgÞsoßzrà
zâä æ®íŒ£ñƲóÿœÛµ©]ÿ6ÿXÅ|qÅrÂ|sŒxu·sr°oqŽgfã |ôÂøÿò¿®ÿP¢ÿO±ÿV€ÿQ¢ÿRÿ_Oÿ8Š}·mÿ<Úwfí{î¡{ægÿZ^ÿHYÿ?UÿBxBpfÿTaÿKYÿCZÿIkÿd|J~dqpzLnjÿAnÿBeÿ@cÿBÿFÌÿWÿFŸÿTÚÿaÝÿcÜÿbÜÿdÝpkÞwoàxáãå«ë¹£ïŲðÿ»ôÿ¿tÿQªÿXÆuÂ~tÀ{s»wrŽrpjlÇ|n÷ÿ÷ÿøÿßhšÿJªÿNµÿUÿQ¢ÿ[ÿ]Kÿ6 uºsÿBÙteë|è}ápBeWÿCZÿ@`ÿLeÿRgÿQ`ÿKXÿC]ÿMhÿZl8mpOzNq}ÿdÿ_~ÿVhÿ@nÿ>²ÿMÐÿ\ÿGÇÿXÚÿaÞjfÝÿbÜÿ_ÜkeÝsmß~và|âäšè¶¢íÁ°ðÿžòÿ¿€qyµÿ\Ãu¿|s»yqºxrŽsrjkÕt÷ÿ÷ÿõÄÌÿW°ÿL°ÿN©ÿO¡ÿSÿ[ÿVNÿ9dx¹zÿI×ÿcìzì{ãoÿbXÿA[ÿFeÿN]ÿKaÿKZÿI[ÿH_ÿQkÿdtDycU
x?iaÿEhÿBnÿDbÿ>ÿAÃÿTÊÿ\ÿLÒÿ^ÝhfÞjfÞÿdÛÿbÜÿbÝpjÞzsßzáâ æ²êŸ®ïƶðÿœÔš¿ÿaŸ}tŸ}vœ|u»zu³tsµolÒÿdî²zøÿëªvÀÿQ«ÿMŠÿLÿM¢ÿXÿYÿ\Mÿ8Vož
ÿQÔÿ_ëyìzãk PeYÿD`ÿIWÿDaÿNbÿP_ÿJ[ÿFcÿSjÿclÿdj9el4egcÿA_ÿ<]ÿ:eÿ;¢ÿHÉÿW®ÿP€ÿQÙÿaÝjgàniàÿdÝÿaÜÿbÝojÞwoß~tß|á
ä¬èºšîŶðÿœñÿ»ºÿ_ÿR§ÿ_³om¶xt¶zvÇ~pÍÿ_Ùkúÿßÿb¯ÿL¢ÿMÿH ÿVÿVÿZÿNLÿ6Lg£ÿZÏÿ]éxí{æjÿc^ÿGWÿ@_ÿK_ÿM_ÿMcÿJXÿB[ÿKj5jcv<mz?hfÿJ]ÿ;Zÿ:Zÿ8ÿ@ŸÿOÅÿRÿDÇÿZÛÿaÞjgàlfàleßÿaÜÿ^ÜÿbÞrjÞ{oßxàã€æ¶€ìÂŽïÿ»óÿ¿ŽpsÿLÿHÿGÿKÿVÀtgÓfç©}öĺÿMÿCÿIÿSÿVÿXÿ]qÿA~ÿGUiÇ©¢\fÌÿ^èxì¡zÝkÿbYÿD]ÿF\ÿE[ÿHbÿMeÿNVÿBZÿD^ÿJuDtkO{Zÿ=Xÿ:Uÿ9iÿ:€ÿHÇÿQÿB¢ÿMØÿ\ÜÿbÞÿdßkgàmhàÿbÝÿ`Üÿ`ÜÿdÝwkßsà|ãå¯éŸ®íǹñÿŸÒÿU ÿUÿNsÿDVÿ;¬ÿ^é¬róœÖÿcÿ@ÿDÿQÿXÿPÿaÿUnÿ?ÿV¡kyÄš€¢mpÊÿ^éyí£zÔ|iÿaXÿC[ÿD]ÿFYÿEbÿPcÿS_ÿMdÿReÿThÿ\Mzu>fWÿ>Vÿ;Xÿ8ÿB®ÿHÿ@ÿFÑÿWÙÿ]ÝÿaÞÿdßjeàmfàngßÿdÜÿdÜÿaÝrgÞ{nßzáãŠæ·šëĶïÿŒìIJÿQ¡ÿWÿTÿO|ÿH·ÿ`ó¿Ðÿ^ÿA{ÿAÿKÿZÿLÿXQgÿQrÿFrÿIVlŸ¡šuwÈÿ\ézï€}ÜoqÿPWÿC_ÿI^ÿH`ÿOjÿZfÿY|CpeÿV_ÿTn3eYrÿbTÿ>Wÿ;cÿ7zÿ<ÿDºÿOÍÿWÓÿY×ÿ\Ûÿ_ÞÿaßkeànfàsjßohÝmeÝÿbÜÿdÝxlÞwáâ ä° è¿±íÿœðÿŒ¢ÿcÿTÿZÿ\¢ÿ[¹ÿ\ÂÿbÿKÿFÿKÿ^ÿJÿKViÿdtÿFmÿCcÿBzÿ[Ê«ŠŸÇÿ^ëzð€ÌzmeÿKYÿD_ÿIcÿOaÿRmÿ_]ÿR
QcÿYlÿ_rÿbr;lr:fSÿ<dÿ7ÿ>¹ÿJÇÿOÏÿVÓÿWÕÿXØÿZÜÿ]Ýÿ`ßÿaßkeàpiàrkßrjßqgÝriÞxkÞ~qà}áâšå·©ëÄ·ìÿ»ž~~ÿQÿ^¥]eµÿZ¶ÿUªÿS¯ÿUÿNÿXÿJÿHÿ` ]oÿSjÿ@jÿ=]ÿ=nÿRØ·«Ò«Çÿ`êxî¢~ÇunbÿGZÿCeÿOoÿTjÿXv>ijÿYv:iw?nt=hgÿQgÿUy@noÿRÿ<³ÿDÇÿMÍÿRÑÿUÒÿV×ÿXÙÿXÝÿ\Ýÿ\ßÿbàjeáphàpiàsiáwkßvjßznàsá}à
á£ä³£èŸ±ìǺ֊ÿUÿWªÿ`ÄÿZÂÿUÍÿXžÿRÿR
ÿVÿRÿX¬gsÿ\fÿ>iÿ@ÿK
\ No newline at end of file
diff --git a/milena/doc/tutorial/samples/tuto4_genericity_and_algorithms.cc b/milena/doc/tutorial/samples/tuto4_genericity_and_algorithms.cc
index ea0d07f..1dac310 100644
--- a/milena/doc/tutorial/samples/tuto4_genericity_and_algorithms.cc
+++ b/milena/doc/tutorial/samples/tuto4_genericity_and_algorithms.cc
@@ -8,7 +8,7 @@ struct keep_specific_colors : public mln::Function_v2b<keep_specific_colors>
{
bool operator()(const mln::value::rgb8& v) const
{
- return v.green() < 20000 && v.blue() > 10000;
+ return v.green() < 200 && v.blue() > 100;
}
};
@@ -83,7 +83,7 @@ int main()
doc::ppmsave(debug::colorize(value::rgb8(), label, nlabels), "tuto4_genericity_and_algorithms");
// \{
- data::fill((lena | (pw::value(label) == pw::cst(16u))).rw(), literal::green);
+ data::fill((lena | (pw::value(label) == pw::cst(0u))).rw(), literal::blue);
// \}
doc::ppmsave(lena, "tuto4_genericity_and_algorithms");
@@ -103,7 +103,7 @@ int main()
lena = duplicate(lena_bak);
// \{
- mln_VAR(object, pw::value(label) == pw::cst(16u));
+ mln_VAR(object, pw::value(label) == pw::cst(0u));
data::fill((extract::green(lena).rw() | object).rw(), literal::max);
// \}
//FIXME: how to display an image which is not defined on a box!?
diff --git a/milena/doc/tutorial/tutorial.tex b/milena/doc/tutorial/tutorial.tex
index 7a4de1b..c4ccd5d 100644
--- a/milena/doc/tutorial/tutorial.tex
+++ b/milena/doc/tutorial/tutorial.tex
@@ -717,9 +717,8 @@ value in \var{label} is equal to 16'.
\begin{center}
\begin{tabular}{c c c c}
\doxyimg{small-enlarged} &
-% \doxyfigure[9]{tuto4_genericity_and_algorithms}{3cm} &
~\huge{\rightarrow}~ &
- \doxyfigure[10]{tuto4_genericity_and_algorithms}{3cm} \\
+ \doxyfigure[9]{tuto4_genericity_and_algorithms}{3cm} \\
\multicolumn{4}{c}{Fill with green a region of interest defined by its
label.} \\
\end{tabular}
--
1.5.6.5
1
0
* mln/essential/routine.hh
* mln/canvas/morpho/connected_filter.hh
* mln/canvas/morpho/all.hh
* mln/all.hh: add missing includes.
* mln/canvas/morpho/algebraic_filter.hh,
* mln/canvas/morpho/algebraic_union_find.hh: move implementation of
find_root()...
* mln/canvas/morpho/internal/find_root.hh: ... here.
* mln/core/image/extension_fun.hh,
* mln/core/image/extension_ima.hh,
* mln/core/image/extension_val.hh: remove extended_with() (duplicate
core/routine/extend).
* mln/value/label.hh
* mln/value/rgb.hh: fix badly closed namespace.
* tests/registration/registration.cc: fix call to registration.
* tests/util/Makefile.am,
* tests/util/set.cc: re-enable this test.
---
milena/ChangeLog | 27 +++++++
milena/mln/all.hh | 1 +
milena/mln/canvas/morpho/algebraic_filter.hh | 25 +------
milena/mln/canvas/morpho/algebraic_union_find.hh | 23 +------
milena/mln/canvas/morpho/all.hh | 2 +
milena/mln/canvas/morpho/connected_filter.hh | 24 ++++---
.../morpho/{all.hh => internal/find_root.hh} | 75 ++++++++++++++++----
milena/mln/core/image/extension_fun.hh | 11 ---
milena/mln/core/image/extension_ima.hh | 13 ----
milena/mln/core/image/extension_val.hh | 11 ---
milena/mln/essential/routine.hh | 1 +
milena/mln/value/label.hh | 5 +-
milena/mln/value/rgb.hh | 7 +-
milena/tests/registration/registration.cc | 6 ++-
milena/tests/util/Makefile.am | 2 +
milena/tests/util/set.cc | 12 ++--
16 files changed, 127 insertions(+), 118 deletions(-)
copy milena/mln/canvas/morpho/{all.hh => internal/find_root.hh} (51%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 81868ae..5727ea3 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,32 @@
2009-02-24 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Various small fixes.
+
+ * mln/essential/routine.hh
+ * mln/canvas/morpho/connected_filter.hh
+ * mln/canvas/morpho/all.hh
+ * mln/all.hh: add missing includes.
+
+ * mln/canvas/morpho/algebraic_filter.hh,
+ * mln/canvas/morpho/algebraic_union_find.hh: move implementation of
+ find_root()...
+ * mln/canvas/morpho/internal/find_root.hh: ... here.
+
+ * mln/core/image/extension_fun.hh,
+ * mln/core/image/extension_ima.hh,
+ * mln/core/image/extension_val.hh: remove extended_with() (duplicate
+ core/routine/extend).
+
+ * mln/value/label.hh
+ * mln/value/rgb.hh: fix badly closed namespace.
+
+ * tests/registration/registration.cc: fix call to registration.
+
+ * tests/util/Makefile.am,
+ * tests/util/set.cc: re-enable this test.
+
+2009-02-24 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Update tutorial.
* doc/tutorial/doxyfile_tuto.local: new doxyfile. Generate only the
diff --git a/milena/mln/all.hh b/milena/mln/all.hh
index f9f16d0..879cd94 100644
--- a/milena/mln/all.hh
+++ b/milena/mln/all.hh
@@ -60,6 +60,7 @@
#include <mln/metal/all.hh>
#include <mln/morpho/all.hh>
#include <mln/norm/all.hh>
+#include <mln/opt/all.hh>
#include <mln/pw/all.hh>
#include <mln/set/all.hh>
#include <mln/tag/all.hh>
diff --git a/milena/mln/canvas/morpho/algebraic_filter.hh b/milena/mln/canvas/morpho/algebraic_filter.hh
index 460bc44..bfcf55e 100644
--- a/milena/mln/canvas/morpho/algebraic_filter.hh
+++ b/milena/mln/canvas/morpho/algebraic_filter.hh
@@ -45,7 +45,7 @@
# include <mln/level/sort_psites.hh>
# include <mln/level/sort_offsets.hh>
-
+# include <mln/canvas/morpho/internal/find_root.hh>
namespace mln
{
@@ -81,17 +81,6 @@ namespace mln
namespace generic
{
- template <typename I>
- inline
- mln_psite(I)
- find_root(I& parent, const mln_psite(I)& x)
- {
- if (parent(x) == x)
- return x;
- else
- return parent(x) = find_root(parent, parent(x));
- }
-
template <typename I, typename N, typename S, typename A>
inline
mln_concrete(I)
@@ -205,18 +194,6 @@ namespace mln
// Fastest version.
-
- template <typename I>
- inline
- unsigned
- find_root_fastest(I& parent, unsigned x)
- {
- if (parent.element(x) == 0)
- return x;
- else
- return parent.element(x) = find_root_fastest(parent, parent.element(x));
- }
-
template <typename I, typename N, typename A>
inline
mln_concrete(I)
diff --git a/milena/mln/canvas/morpho/algebraic_union_find.hh b/milena/mln/canvas/morpho/algebraic_union_find.hh
index a19ace8..75ac3f6 100644
--- a/milena/mln/canvas/morpho/algebraic_union_find.hh
+++ b/milena/mln/canvas/morpho/algebraic_union_find.hh
@@ -41,6 +41,7 @@
# include <mln/data/fill.hh>
# include <mln/util/pix.hh>
+# include <mln/canvas/morpho/internal/find_root.hh>
namespace mln
{
@@ -69,17 +70,6 @@ namespace mln
namespace generic
{
- template <typename I>
- inline
- mln_psite(I)
- find_root(I& parent, const mln_psite(I)& x)
- {
- if (parent(x) == x)
- return x;
- else
- return parent(x) = find_root(parent, parent(x));
- }
-
template <typename I, typename N, typename F>
inline
mln_concrete(I)
@@ -219,17 +209,6 @@ namespace mln
// Fastest version.
- template <typename I>
- inline
- unsigned
- find_root_fastest(I& parent, unsigned x)
- {
- if (parent.element(x) == x)
- return x;
- else
- return parent.element(x) = find_root_fastest(parent, parent.element(x));
- }
-
template <typename I, typename N, typename F>
inline
diff --git a/milena/mln/canvas/morpho/all.hh b/milena/mln/canvas/morpho/all.hh
index d3847db..5720829 100644
--- a/milena/mln/canvas/morpho/all.hh
+++ b/milena/mln/canvas/morpho/all.hh
@@ -46,8 +46,10 @@ namespace mln
}
+# include <mln/canvas/morpho/internal/find_root.hh>
# include <mln/canvas/morpho/algebraic_filter.hh>
# include <mln/canvas/morpho/algebraic_union_find.hh>
+//# include <mln/canvas/morpho/connected_filter.hh>
#endif // ! MLN_CANVAS_MORPHO_ALL_HH
diff --git a/milena/mln/canvas/morpho/connected_filter.hh b/milena/mln/canvas/morpho/connected_filter.hh
index beec8e4..d092a08 100644
--- a/milena/mln/canvas/morpho/connected_filter.hh
+++ b/milena/mln/canvas/morpho/connected_filter.hh
@@ -32,7 +32,8 @@
/// \file mln/canvas/morpho/connected_filter.hh
///
/// Connected filters dispatch (algebraic & leveling filters).
-///
+
+
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
# include <mln/core/concept/accumulator.hh>
@@ -42,6 +43,9 @@
# include <mln/level/sort_psites.hh>
# include <mln/level/sort_offsets.hh>
+# include <mln/util/pix.hh>
+
+# include <mln/data/fill.hh>
namespace mln {
namespace canvas {
@@ -181,9 +185,9 @@ namespace mln {
// Initialization.
{
initialize(deja_vu, input);
- mln::data::fill(deja_vu, false);
+ data::fill(deja_vu, false);
initialize(activity, input);
- mln::data::fill(activity, true);
+ data::fill(activity, true);
initialize(parent, input);
initialize(data, input);
//a.init(); // init required.
@@ -304,11 +308,11 @@ namespace mln {
// Initialization.
{
initialize(deja_vu, input);
- mln::data::fill(deja_vu, false);
+ data::fill(deja_vu, false);
initialize(activity, input);
- mln::data::fill(activity, true);
+ data::fill(activity, true);
initialize(parent, input);
- mln::data::fill(parent, 0);
+ data::fill(parent, 0);
initialize(data, input);
}
@@ -506,7 +510,7 @@ namespace mln {
template <typename I, typename N, typename A>
inline
mln_concrete(I)
- connected_filter_dispatch(mln::trait::accumulator::when_pix::use_none,
+ connected_filter_dispatch(trait::accumulator::when_pix::use_none,
const Image<I>& input,
const Neighborhood<N>& nbh,
const Accumulator<A>& a,
@@ -519,7 +523,7 @@ namespace mln {
template <typename I, typename N, typename A>
inline
mln_concrete(I)
- connected_filter_dispatch(mln::trait::accumulator::when_pix::use_p,
+ connected_filter_dispatch(trait::accumulator::when_pix::use_p,
const Image<I>& input,
const Neighborhood<N>& nbh,
const Accumulator<A>& a,
@@ -532,7 +536,7 @@ namespace mln {
template <typename I, typename N, typename A>
inline
mln_concrete(I)
- connected_filter_dispatch(mln::trait::accumulator::when_pix::use_v,
+ connected_filter_dispatch(trait::accumulator::when_pix::use_v,
const Image<I>& input,
const Neighborhood<N>& nbh,
const Accumulator<A>& a,
@@ -545,7 +549,7 @@ namespace mln {
template <typename I, typename N, typename A>
inline
mln_concrete(I)
- connected_filter_dispatch(mln::trait::accumulator::when_pix::use_pix,
+ connected_filter_dispatch(trait::accumulator::when_pix::use_pix,
const Image<I>& input,
const Neighborhood<N>& nbh,
const Accumulator<A>& a,
diff --git a/milena/mln/canvas/morpho/all.hh b/milena/mln/canvas/morpho/internal/find_root.hh
similarity index 51%
copy from milena/mln/canvas/morpho/all.hh
copy to milena/mln/canvas/morpho/internal/find_root.hh
index d3847db..8011122 100644
--- a/milena/mln/canvas/morpho/all.hh
+++ b/milena/mln/canvas/morpho/internal/find_root.hh
@@ -1,5 +1,4 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
-// Laboratory (LRDE)
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -26,28 +25,76 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_CANVAS_MORPHO_ALL_HH
-# define MLN_CANVAS_MORPHO_ALL_HH
+#ifndef MLN_CANVAS_MORPHO_FIND_ROOT_HH
+# define MLN_CANVAS_MORPHO_FIND_ROOT_HH
-/// \file mln/canvas/morpho/all.hh
+/// \file mln/canvas/morpho/internal/find_root.hh.hh
///
-/// File that includes morphological canvas-related routines.
-
+/// Routines to handle parent image.
+///
+/// \todo write a 'parent' image instead?
namespace mln
{
+
namespace canvas
{
- /// Namespace of morphological canvas.
- namespace morpho {}
+ namespace morpho
+ {
+
+ namespace internal
+ {
+
+ template <typename I>
+ inline
+ mln_psite(I)
+ find_root(I& parent, const mln_psite(I)& x);
+
+
+ template <typename I>
+ inline
+ unsigned
+ find_root_fastest(I& parent, unsigned x);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I>
+ inline
+ mln_psite(I)
+ find_root(I& parent, const mln_psite(I)& x)
+ {
+ if (parent(x) == x)
+ return x;
+ else
+ return parent(x) = find_root(parent, parent(x));
+ }
+
+
+ template <typename I>
+ inline
+ unsigned
+ find_root_fastest(I& parent, unsigned x)
+ {
+ if (parent.element(x) == 0)
+ return x;
+ else
+ return parent.element(x) = find_root_fastest(parent,
+ parent.element(x));
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::canvas::morpho::internal
- }
-}
+ } // end of namespace mln::canvas::morpho
+ } // end of namespace mln::canvas
-# include <mln/canvas/morpho/algebraic_filter.hh>
-# include <mln/canvas/morpho/algebraic_union_find.hh>
+} // end of namespace mln
+#endif // ! MLN_CANVAS_MORPHO_FIND_ROOT_HH
-#endif // ! MLN_CANVAS_MORPHO_ALL_HH
diff --git a/milena/mln/core/image/extension_fun.hh b/milena/mln/core/image/extension_fun.hh
index 0cd09b6..67e5bb4 100644
--- a/milena/mln/core/image/extension_fun.hh
+++ b/milena/mln/core/image/extension_fun.hh
@@ -267,17 +267,6 @@ namespace mln
target = model.extension();
}
- template <typename I, typename F>
- extension_fun<I,F>
- extended_with(Image<I>& ima, const Function_v2v<F>& f)
- {
- mlc_not_equal(mln_trait_image_ext_domain(I),
- trait::image::ext_domain::none)::check();
- mln_precondition(exact(ima).is_valid());
- extension_fun<I,F> tmp(exact(ima), exact(f));
- return tmp;
- }
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
diff --git a/milena/mln/core/image/extension_ima.hh b/milena/mln/core/image/extension_ima.hh
index 98360b4..91055dd 100644
--- a/milena/mln/core/image/extension_ima.hh
+++ b/milena/mln/core/image/extension_ima.hh
@@ -268,19 +268,6 @@ namespace mln
target_ = ext_;
}
-
- template <typename I, typename J>
- extension_ima<I,J>
- extended_with(Image<I>& ima, const Image<J> ext)
- {
- mlc_not_equal(mln_trait_image_ext_domain(I),
- trait::image::ext_domain::none)::check();
- mln_precondition(exact(ima).is_valid());
- mln_precondition(exact(ext).is_valid());
- extension_ima<I,J> tmp(exact(ima), exact(ext));
- return tmp;
- }
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
diff --git a/milena/mln/core/image/extension_val.hh b/milena/mln/core/image/extension_val.hh
index 9dbfadc..63dbeb7 100644
--- a/milena/mln/core/image/extension_val.hh
+++ b/milena/mln/core/image/extension_val.hh
@@ -268,17 +268,6 @@ namespace mln
target = static_cast<V>(model.extension());
}
- template <typename I>
- extension_val<I>
- extended_with(Image<I>& ima, const mln_value(I)& val)
- {
- mlc_not_equal(mln_trait_image_ext_domain(I),
- trait::image::ext_domain::none)::check();
- mln_precondition(exact(ima).is_valid());
- extension_val<I> tmp(exact(ima), val);
- return tmp;
- }
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
diff --git a/milena/mln/essential/routine.hh b/milena/mln/essential/routine.hh
index ba164b4..434519f 100644
--- a/milena/mln/essential/routine.hh
+++ b/milena/mln/essential/routine.hh
@@ -57,6 +57,7 @@
# include <mln/metal/essential.hh>
# include <mln/morpho/essential.hh>
# include <mln/norm/essential.hh>
+# include <mln/opt/essential.hh>
# include <mln/pw/essential.hh>
# include <mln/registration/essential.hh>
# include <mln/set/essential.hh>
diff --git a/milena/mln/value/label.hh b/milena/mln/value/label.hh
index ceabea5..53c3d60 100644
--- a/milena/mln/value/label.hh
+++ b/milena/mln/value/label.hh
@@ -275,10 +275,11 @@ namespace mln
return ostr << debug::format(i.to_equiv());
}
-# endif // ! MLN_INCLUDE_ONLY
-
} // end of namespace mln::value
+
+# endif // ! MLN_INCLUDE_ONLY
+
} // end of namespace mln
diff --git a/milena/mln/value/rgb.hh b/milena/mln/value/rgb.hh
index 2bd1b8b..2d13f94 100644
--- a/milena/mln/value/rgb.hh
+++ b/milena/mln/value/rgb.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -725,8 +726,6 @@ namespace mln
return istr >> c.red() >> c.green() >> c.blue();
}
-# endif // ! MLN_INCLUDE_ONLY
-
} // end of namespace mln::value
@@ -792,5 +791,7 @@ namespace mln
} // end of namespace mln
+# endif // ! MLN_INCLUDE_ONLY
+
#endif // ! MLN_VALUE_RGB_HH
diff --git a/milena/tests/registration/registration.cc b/milena/tests/registration/registration.cc
index 4129b5b..9433f5a 100644
--- a/milena/tests/registration/registration.cc
+++ b/milena/tests/registration/registration.cc
@@ -54,6 +54,10 @@ int main()
typedef p_array<point3d> arr_t;
arr_t arr1 = convert::to<arr_t>(img1);
arr_t arr2 = convert::to<arr_t>(img2);
- registration::registration1(arr1,arr2);
+
+ box3d bbox = img2.bbox();
+ bbox.enlarge(1, 10);
+ bbox.enlarge(2, 10);
+ registration::registration1(bbox, arr1, arr2);
//FIXME: Auto test result
}
diff --git a/milena/tests/util/Makefile.am b/milena/tests/util/Makefile.am
index f6b4306..b348587 100644
--- a/milena/tests/util/Makefile.am
+++ b/milena/tests/util/Makefile.am
@@ -13,6 +13,7 @@ check_PROGRAMS = \
lemmings \
line_graph \
ord_pair \
+ set \
soft_heap \
tree \
tree_fast \
@@ -29,6 +30,7 @@ lazy_set_SOURCES = lazy_set.cc
lemmings_SOURCES = lemmings.cc
line_graph_SOURCES = line_graph.cc
ord_pair_SOURCES = ord_pair.cc
+set_SOURCES = set.cc
soft_heap_SOURCES = soft_heap.cc
tree_SOURCES = tree.cc
tree_fast_SOURCES = tree_fast.cc
diff --git a/milena/tests/util/set.cc b/milena/tests/util/set.cc
index 7dc23ef..f97449f 100644
--- a/milena/tests/util/set.cc
+++ b/milena/tests/util/set.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008, 2009 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
@@ -25,12 +25,10 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*!
- * \file tests/util/set.cc
- *
- * \brief test of mln::util::set
- *
- */
+///
+/// \file tests/util/set.cc
+///
+/// test of mln::util::set
#include <mln/util/set.hh>
--
1.5.6.5
1
0
* doc/tutorial/doxyfile_tuto.local: new doxyfile. Generate only the
tutorial.
* doc/tutorial/figures/extend-1.ppm,
* doc/tutorial/figures/extend-2.ppm,
* doc/tutorial/figures/extend-3.ppm,
* doc/tutorial/figures/extend-4.ppm,
* doc/tutorial/figures/extend-5.ppm,
* doc/tutorial/outputs/extend.txt: new reference files for the new
example.
* doc/tutorial/samples/Makefile.am,
* doc/tutorial/samples/extend.cc: new example for the tutorial,
related to the image extension.
* doc/tutorial/samples/ima2d-rot.cc: use extended_to().
* doc/tutorial/tools/todoxygen.sh: support keyword subsubsection.
* doc/tutorial/tutorial.tex: add more details about image extension.
---
milena/ChangeLog | 25 +++
milena/doc/tutorial/doxyfile_tuto.local | 342 ++++++++++++++++++++++++++++++
milena/doc/tutorial/figures/extend-1.ppm | Bin 0 -> 12406 bytes
milena/doc/tutorial/figures/extend-2.ppm | Bin 0 -> 16546 bytes
milena/doc/tutorial/figures/extend-3.ppm | Bin 0 -> 16546 bytes
milena/doc/tutorial/figures/extend-4.ppm | 7 +
milena/doc/tutorial/figures/extend-5.ppm | Bin 0 -> 12406 bytes
milena/doc/tutorial/samples/Makefile.am | 2 +
milena/doc/tutorial/samples/extend.cc | 94 ++++++++
milena/doc/tutorial/samples/ima2d-rot.cc | 2 +-
milena/doc/tutorial/tools/todoxygen.sh | 2 +-
milena/doc/tutorial/tutorial.tex | 80 +++++++-
12 files changed, 545 insertions(+), 9 deletions(-)
create mode 100644 milena/doc/tutorial/doxyfile_tuto.local
create mode 100644 milena/doc/tutorial/figures/extend-1.ppm
create mode 100644 milena/doc/tutorial/figures/extend-2.ppm
create mode 100644 milena/doc/tutorial/figures/extend-3.ppm
create mode 100644 milena/doc/tutorial/figures/extend-4.ppm
create mode 100644 milena/doc/tutorial/figures/extend-5.ppm
create mode 100644 milena/doc/tutorial/outputs/extend.txt
create mode 100644 milena/doc/tutorial/samples/extend.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index b2951e8..81868ae 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,28 @@
+2009-02-24 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Update tutorial.
+
+ * doc/tutorial/doxyfile_tuto.local: new doxyfile. Generate only the
+ tutorial.
+
+ * doc/tutorial/figures/extend-1.ppm,
+ * doc/tutorial/figures/extend-2.ppm,
+ * doc/tutorial/figures/extend-3.ppm,
+ * doc/tutorial/figures/extend-4.ppm,
+ * doc/tutorial/figures/extend-5.ppm,
+ * doc/tutorial/outputs/extend.txt: new reference files for the new
+ example.
+
+ * doc/tutorial/samples/Makefile.am,
+ * doc/tutorial/samples/extend.cc: new example for the tutorial,
+ related to the image extension.
+
+ * doc/tutorial/samples/ima2d-rot.cc: use extended_to().
+
+ * doc/tutorial/tools/todoxygen.sh: support keyword subsubsection.
+
+ * doc/tutorial/tutorial.tex: add more details about image extension.
+
2009-02-23 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add DICOM support.
diff --git a/milena/doc/tutorial/doxyfile_tuto.local b/milena/doc/tutorial/doxyfile_tuto.local
new file mode 100644
index 0000000..a026b2e
--- /dev/null
+++ b/milena/doc/tutorial/doxyfile_tuto.local
@@ -0,0 +1,342 @@
+# Doxyfile 1.5.6
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = "Milena (Olena)"
+PROJECT_NUMBER = "User documentation 1.0 $Id: ChangeLog 2542 2008-10-10 13:35:03Z ballas $"
+OUTPUT_DIRECTORY = ./user/
+CREATE_SUBDIRS = YES
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF =
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = ../../../milena \
+ ../../milena
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+BUILTIN_STL_SUPPORT = YES
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+IDL_PROPERTY_SUPPORT = YES
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+TYPEDEF_HIDES_STRUCT = NO
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = YES
+HIDE_IN_BODY_DOCS = YES
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = YES
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = YES
+SORT_GROUP_NAMES = YES
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = YES
+SHOW_FILES = YES
+SHOW_NAMESPACES = YES
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = YES
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = .
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS = *.cc \
+ *.hh \
+ *.hxx \
+ *.hcc
+RECURSIVE = YES
+EXCLUDE = user
+EXCLUDE_SYMLINKS = YES
+EXCLUDE_PATTERNS = *spe.hh
+EXCLUDE_SYMBOLS = *::internal*
+EXAMPLE_PATH = /lrde/stockholm/lazzara/svn/olena/git/oln/milena/doc/tutorial/samples \
+ /lrde/stockholm/lazzara/svn/olena/git/oln/milena/doc/tutorial/outputs \
+ /lrde/stockholm/lazzara/svn/olena/git/oln/milena/doc/tutorial/examples \
+ /lrde/stockholm/lazzara/svn/olena/git/oln/milena/doc/examples \
+ /lrde/stockholm/lazzara/svn/olena/git/build/milena/doc/tutorial/samples \
+ /lrde/stockholm/lazzara/svn/olena/git/build/milena/doc/tutorial/outputs
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH = /lrde/stockholm/lazzara/svn/olena/git/oln/milena/doc/tutorial/figures \
+ /lrde/stockholm/lazzara/svn/olena/git/build/milena/doc/tutorial/figures \
+ /lrde/stockholm/lazzara/svn/olena/git/oln/milena/img
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_BUNDLE_ID = org.doxygen.Project
+HTML_DYNAMIC_SECTIONS = YES
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+CHM_INDEX_ENCODING =
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = FRAME
+TREEVIEW_WIDTH = 250
+FORMULA_FONTSIZE = 10
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = YES
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = YES
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED = "mlc_unqualif(T)=typename mln::metal::unqualif<T>::ret" \
+ "mln_piter(T)=typename T::piter" \
+ "mln_fwd_piter(T)=typename T::fwd_piter" \
+ "mln_bkd_piter(T)=typename T::bkd_piter" \
+ "mln_qiter(T)=typename T::qiter" \
+ "mln_fwd_qiter(T)=typename T::fwd_qiter" \
+ "mln_bkd_qiter(T)=typename T::bkd_qiter" \
+ "mln_niter(T)=typename T::niter" \
+ "mln_fwd_niter(T)=typename T::fwd_niter" \
+ "mln_bkd_niter(T)=typename T::bkd_niter" \
+ "mln_viter(T)=typename T::viter" \
+ "mln_fwd_viter(T)=typename T::fwd_viter" \
+ "mln_bkd_viter(T)=typename T::bkd_viter" \
+ "mln_result(T)=typename T::result" \
+ "mln_enc(T)=typename T::enc" \
+ "mln_value(T)=typename T::value" \
+ "mln_qlf_value(T)=typename T::qlf_value" \
+ "mln_pset(T)=typename T::pset" \
+ "mln_sum(T)=typename mln::value::props<T>::sum" \
+ "mln_vset(T)=typename T::vset" \
+ "mln_rvalue(T)=typename T::rvalue" \
+ "mln_lvalue(T)=typename T::lvalue" \
+ "mln_mesh(T)=typename T::mesh" \
+ "mln_coord(T)=typename T::coord" \
+ "mln_site(T)=typename T::site" \
+ "mln_psite(T)=typename T::psite" \
+ "mln_dpsite(T)=typename T::dpsite" \
+ "mln_accu_with(A, T)=typename A::template with< T >::ret" \
+ "mln_trait_op_plus(L, R)=typename mln::trait::op::plus< L , R >::ret" \
+ "mln_trait_op_minus(L, R)=typename mln::trait::op::minus< L , R >::ret" \
+ "mln_trait_op_times(L, R)=typename mln::trait::op::times< L , R >::ret" \
+ "mln_trait_op_div(L, R)=typename mln::trait::op::div< L , R >::ret" \
+ "mln_trait_op_mod(L, R)=typename mln::trait::op::mod< L , R >::ret" \
+ "mln_trait_op_uminus(T)=typename mln::trait::op::uminus< T >::ret" \
+ "mln_ch_value(I, V)=typename mln::trait::ch_value< I, V >::ret" \
+ "mlc_unqualif_(T)=mln::metal::unqualif<T>::ret" \
+ "mln_piter_(T)=T::piter" \
+ "mln_fwd_piter_(T)=T::fwd_piter" \
+ "mln_bkd_piter_(T)=T::bkd_piter" \
+ "mln_qiter_(T)=T::qiter" \
+ "mln_fwd_qiter_(T)=T::fwd_qiter" \
+ "mln_bkd_qiter_(T)=T::bkd_qiter" \
+ "mln_niter_(T)=T::niter" \
+ "mln_fwd_niter_(T)=T::fwd_niter" \
+ "mln_bkd_niter_(T)=T::bkd_niter" \
+ "mln_viter_(T)=T::viter" \
+ "mln_fwd_viter_(T)=T::fwd_viter" \
+ "mln_bkd_viter_(T)=T::bkd_viter" \
+ "mln_result_(T)=T::result" \
+ "mln_enc_(T)=T::enc" \
+ "mln_value_(T)=T::value" \
+ "mln_qlf_value_(T)=T::qlf_value" \
+ "mln_pset_(T)=T::pset" \
+ "mln_sum_(T)=mln::value::props<T>::sum" \
+ "mln_vset_(T)=T::vset" \
+ "mln_rvalue_(T)=T::rvalue" \
+ "mln_lvalue_(T)=T::lvalue" \
+ "mln_mesh_(T)=T::mesh" \
+ "mln_coord_(T)=T::coord" \
+ "mln_site_(T)=T::site" \
+ "mln_psite_(T)=T::psite" \
+ "mln_dpsite_(T)=T::dpsite" \
+ "mln_accu_with_(A, T)=A::template with< T >::ret" \
+ "mln_trait_op_plus_(L, R)=mln::trait::op::plus< L , R >::ret" \
+ "mln_trait_op_minus_(L, R)=mln::trait::op::minus< L , R >::ret" \
+ "mln_trait_op_times_(L, R)=mln::trait::op::times< L , R >::ret" \
+ "mln_trait_op_div_(L, R)=mln::trait::op::div< L , R >::ret" \
+ "mln_trait_op_mod_(L, R)=mln::trait::op::mod< L , R >::ret" \
+ "mln_trait_op_uminus_(T)=mln::trait::op::uminus< T >::ret" \
+ "mln_ch_value_(I, V)=typename mln::trait::ch_value< I, V >::ret" \
+ "mln_ch_value(I, V)_=mln::trait::ch_value< I, V >::ret" \
+ "mln_morpher_lvalue(I)=typename internal::morpher_lvalue_<I>::ret" \
+ "mln_concrete(I)=typename mln::trait::concrete< I >::ret" \
+ "mln_concrete_ch_value(I, V)=typename mln::trait::ch_value< typename mln::trait::concrete< I >::ret, V >::ret" \
+ "mlc_const(T)=typename mln::metal::const_< T >::ret" \
+ "mlc_const_return(T)=typename mln::metal::const_return_< T >::ret" \
+ "mln_element(T)=typename T::element" \
+ "mln_element_(T)=T::element" \
+ "mln_delta(T)=typename T::delta" \
+ "mln_delta_(T)=T::delta" \
+ "mln_dpoint(T)=typename T::dpoint" \
+ "mln_dpoint_(T)=T::dpoint" \
+ "mln_point(T)=typename T::point" \
+ "mln_point_(T)=T::point" \
+ "mln_gradient_component(I)=typename mln::trait::ch_value< I, mln::value::props< typename I::value >::sum >::ret" \
+ "mln_gradient(I)=mln::value::stack_image< I::point::dim, mln::trait::ch_value< I, mln::value::props< typename I::value >::sum >::ret >"
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+MSCGEN_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = YES
+DOT_FONTNAME = FreeSans
+DOT_FONTPATH =
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = YES
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
+MAX_DOT_GRAPH_DEPTH = 1000
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/milena/doc/tutorial/figures/extend-1.ppm b/milena/doc/tutorial/figures/extend-1.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..ccc5f9e76fb35adf4fbedd54004c2b400ee122cf
GIT binary patch
literal 12406
zcmai4XH-+^y1u_>-FwbGa}@y_mMP9SIF61LlR!cZp_ATwLP!PDLjnl|M7lKTHc+Gp
zDosFo?@EVIY=el-%sJ<-`|D;7e{$CT)*9CS@vd(_yzjH${eExxc0w+Eal*})Bj(5%
zF&wrVQ|*Qkh&W<~+gbM?-Q4&wG14n%&Pe`PaTm$i9CwaX5W{fi%I*K<9pWG1=@!OO
za2RqH-;E(=yP-I79FasC%@N1A1u~ctyHbf<?e=Y87|Q$97Z=XET{!>6Pe1?s#eYEl
ze#wX#V{<BCxEen~JsSHMjfFt|W0XZ3V>2eX%oz@2lEawbu%MVpo_(D$#$}DN7{e^)
zFp~krtXO5s2H}cPyqXZb8qZ%f@}QVz0;QcyX`?b<kSX0%S~rCX#W=3KPZf^Rh?Q4E
z9wEaT{lg#og*x8dlP6fT2^M9NO`l=YrvA79-2Qkj7H!=Aq)hq<ojO9NLG`Se6*jYE
z-4eZF5v?Z(Y$iSw(-=l*BT_m@lui=G{s_Gk3KZkG^4c6V%A{3z1l4&3HTj1%_=Y&%
z-IFJov<W7Cibb7f(f_!Z0G~|p*b^M)IEyjHq>eFYqf~(1C4*ukHEuISwv{T~us=nD
z2x_Y#oX~<LbrQ*)6lxcZ(a&T;F^(&5EW&XbuHsTatyfT^Us!`5fd2%II?iBBF{o1v
z+6;{{#Q^w!oKBx$G40nVjWSB3j#9~vR`%otP3(qMxnYf2PnK*X3D-gVr_-cOVYm(w
zxr<EhqR@s|f68AlPK~tlf8-VX*f*r!Cm3pXoI)C>(WYtC2|9g}!J480{69jajWSqc
zEY2v6Hg4w+dhf3k(p6K8%@VU_k=PPNwnQ=1);}l9nrY0|a9kIeVt0O_2Y`>`f4wye
zM=98{3xDu$^a*JI@+XrgDfCGSb&^J#qA{jGd#ay89VAmnDD+VZeT>c;r_dd(?8&nd
z(V|+mVvJc!kgOTSHe(bN^M8x?*Y6nWgRpIQO5wF2;y#!o=1sEXeTM9{k+Ui$y*BgS
zq(~g^?#a)5gSvtvhOxL20)CuK7$*ZFVK7$TqfH!4xjt5qGkvdQ@@^4S&ls6DN}>$n
z$em%NXBa|P1Yk$lw7iu#&b*v6CuP2pF;`4Ns2<iKB;%kLW&btWzN_!kq`#y^&vCF*
z6ztn%;rkoWP<)e5a0e!0AR=-IPZ%TM$4Epd=7lt_U!xyPNF2>fo4A!beYXIL8NgHR
z<h#QO?LoLE|Hz(j5)`wnU@a+F3sTm+n6V(C&q)9~i{au)b@rqjfYT3L-N{vKX;`&z
z|6xMJyA;7MApZ5<q0Iqd-64^^;n+buag+$K`&=OF7AtyGx?!tjx+Lf2{X!_Wrx;vE
z2);9v(2OBG_KkQE3edAGWv(dLi!%EouovZ=MFkhChk5`(bw<!#;P@{uZ>LH|i4lco
zeTIqHUs8nI=`tw378UXo9nlqv?+(KbM&d_s1SqCg7~Lb1^(o?p;tdnIX><1h@iSaf
z{2&0=WUq<7k##=Uju1fntjXAG3eK{WwJhVTD7b5J0;nzeK_u-EitXlOg-6=t^s1`?
zB|rNOlW^~?g6#}I{MVtv{>4ACHv&I|BMjp~{Q08(C~?13KB`j9WTh-t1Nd*x_6-#m
zRCr(>Aj9u_MzjS3{J*B)+vJ=TDQ8v2Ta$6ORDc~#c11;hA7=KzPv~Pi12LtS0?ID<
z4iRy0Eq4D)q0d|A9r`RFtSc1T7lE_$A0hzw4~e2jq|z~kVoVt~o0>RRk_pxGdhEsa
z{BVOznRgLg<`L40!9y`CGNDb*Taj?qWc&>Uf1E{!Vz?(UDM(JQQZ=HBh2DK<5seUW
zH_!Oo_P{*!3avo`@@;zvzAXg*Jc87Yr*$*9{d_>(w6)c3bTzJbHm$ZlUhi$*=xv7D
zT8)X?(n~jV@_quD?+i1X^nzjt|Lq|-jAT0_nD&@IfM6c>fnpq2-de;XBtq_w0TovQ
zA9@BqLIL`p)*$TjU~ESO=>>@~$P<l908zL4<o;4))oM%KMo;r*Z_7r1tD}`Yc}2$C
z(n~h9@&O`M><Xv-^&%9*c82o~deU7y?P-VU>dAHsfMOh1-dZFhWMa0vU)d#eH4Ibj
z3GzP%+Yy9)5lI<ja7F~8VF4gZFFh!;wLDsDtFv`9u68|J>jwCLNy^{UMQ`e4{UoZ$
z6@mZjB}XQEGVc(QeHg_&=*6<<d?!RD9#Eql|LdJ4dYFLC_};tZLO>0|-o;@Y@9xR%
zn8=P`TpyX)M`3o;*h4Hf6tmKBce&x-O4EboCpEVAKLQDgnHO_k$BQ@g;w~J4?Br1(
zPk>@LcIP|6C{A$pL8SQ#c|@y&VjNd~NfnP$2zh6`E3csKEodVu$nox;{LDY{MFgQ2
zN9`rC2btUs0-(w)R+r7+E?#<AvD#F<)>60D-T>9JWLCb`b5@n?r&LZ?N%2x!Jru)m
zhST<4W4pj<&d6?=cFbUaVjNdKWXLAy_<}R2+gAhYkU<Sdfd8Ak!`d*|UM#f_PwOJF
zr{ffk8usM5!kop5g5`U~OI0Pyb@q2r1;wm1+}qF#R?2eL+8(TSHEs;FKru8Y7<Jz@
zuB%rmnlq`>&svR+7<-de<B6&FM33OZ-z7(V%m*;3^9+3AjcGsx{oZ7G$)~gihC6E5
zlSiboS%dy%a^ie$=6rs}T+VeUX1@0ReB;A~+Iz36Z@+wWZ{ltR6tmIWvesJrdhq$y
zNGoo?C*9c-ig}r0oUt0FlXO!_+6SIN4-l9d1bPr3@y;sT$%}#F>k;Ti6y~va$lse1
z*EF073LtOKYLruI&6HO6GR3l(owk^F1FC1fx^nJr+1#CqnWDU@vciShQYgmORy&(_
zW3jrlF*%vwgrGUYp_rGc#+ekuOp5(oXsZyI`>=oqu)t9w?p;dM_Dw)VsPjZOc%d86
z5x>`I?LF$e08sbGrLwU&<%~u<XHJ;2SYD;3LhZh~nLT?mXCgCeuHxoOZLzHt5K*(Y
zvd6ER=S%W5NDBD?+<rmzOsB?ATlLc^x@oJ<?*D2;P$LpEW$zzSqCVsU{9lJa*TMZ8
zLvjCXO@5ypy{@4{bq)$-<MP-Um98^N|AcL*<C>tD{&?#|TH5m6TwBwf_161~O?RP~
zHi@Kx%$>ep8u2#|dy~mLgoI+Ill4={+DWT!(xR<FhCD!qJo65EMaBMdJ!+=_z`p^G
zehl}s4`Tn@mHw$xu@D7_pCMlKge10uqj^eKS7Ia<7@!ZiC(_NA7py<Mx7Jd<+WK&@
z`5~0sZC~80Te&IWOtKTqe%X@`6f>C=Kar#xx9BF#>Uy8BS}#m9%FaLX{dLiYJiz{~
zM+DZx{O?}y{k0|aw`$cimk!lAE)chq<*gKDwqLCNJUjX%phuc1$Xux}TX|N!+;nI8
zX%&$FN?B$qnn>9XV>rR+_RM+24{B?|nlPE9AGcp-J@oEQw)7RBl;iGQc{$)AEU?xy
z5Q^!e(T3>!UMjbn#OtN<dzgTls5nhFpwxVKR@5c_6S3k|c|KH6>vc<ZxUhn$du7tT
z&Q!mv1nin&rDnz&|0+A-WmdvWdcxFoK#g<M{4qy9&!=Ra_AbBZZ{OFoaJ1vyJ-LTO
z>7xm{h`cVUqKBgBBt=6pLbuRpcec`BTS7O^-!57KMf;75kvYNQO15FzY~Cs|CBgx<
zvL{A0pPTT~&Ob9@HZx&5?N9jc<|*tMCi^tXJ`_BFV;;c){vV{$TOwFpBvB7V)Qp#B
zT;o9bbB~9_{=`WQPkNqOuuxqx1Dc4tNlfD<LSCezPoHEw?L++X8dOiOUiT``Je!>`
zn`P&3noduIVjNdK=Ef~V(Q|+BF1r+1g9xto3UR!<C%1(V+Oe!Y0=JjQxBM6?`8o`W
z;hgY)KvFar^5?5d=4;AFb2FfrMRly=h*$j2#BM{Hz~1NV2k;*@>!#C<v)QJZjQH6M
z<7@^XvpH)1m>)YQV&t9;sJMi#LxweY1GsgD;`>SL<}kMIR4~WYM*!mA#uG0TWcA!A
zoVr^vQ+aDDC*9G?p1fV0mG+Gn+ts^SnIt;l&pimJw&SVsLy7vK1pR2Te%xx9y74Fc
zck*LjiI{n311miKbp+}I;6Fy;wA13u?qU3I2*mw9!mlEs++HS|mhKkz<(JIfE1ykE
zv02Pe%;zWfYG6UQFX6QUUF<h#-VqcOGnHu^&oGXqnTC_~FO2r<-}=vbRPZBv3jsrS
zghXy7DLxcxpc)!cq3!6<!SKj&D)ku=Uljz%jpY4aoMXZKuZZ+xp;_LfQHv3(=Y3Jm
zc2VZegQA_sw|85retQAvHlx4xW4It_E}n%UysntonRGz6*%fc-(CIog+Fp&yKAYG1
zgg%6!pJT$_SY$heYN*}EUYHiYkiH1Qf;{R@I62*m3B|CF2GE>+gx`}C?!m+Hy49*Y
zD5jgld2=J_Ls|AtZTW|)!cirlR`T6YOjiW=i0@;rd{D1?nf7nq-qSgllGu}IYS+g%
z$u$qXf*&A)ZeR9m_6vSv5q~U>gW9e2@b6>@=5*p!t@t^Mt33_Ka?<l`h6^h4%WF>s
z;+3*ATMMAJP7@hxQpJb-^v})rAJcip(|}2k<pN{6!sXuucgkZXt(s{oARY#iOfQUv
zHm%`FobG{F@I4r&=)6w@D)3FR_+tsc|CJYg>sZ3&4AXNuQ~e!A_&pW+jO6_=ypyNt
zGGR0|X}PZQRrM_>W&nd*VheXl^OkO9ntlqu;R86^VK`r-xxjA*F#6ST)2Z6YBmn;|
zy{<V<Q!i6J)9GuyL#yDJqMv;1P5zrC@ot$GYPT$q+pV_N$El;-sq#x=-gkihlf3^L
z#nrPzu3WlvbNX)K00|IdQ#krOjkj~ZVyQ5{hpT!XZG_sQ9k|9l;#J2M4;eL+$(k{<
z3W{ltRdvQ|W{VRxYLe~oQ+gSlecJ2(RlhB>bhjM9{~24OyTW0*h48;)S|U@UegsUr
zk^2xu{<xPpsWVkYPyNDP(gD7mV~G}socARq@0#nEbjB%06qFm?*+cS`Z@WZ3o^0>X
zG@}WCc$msdc++Tk*JOUzXn|_@T&`P<VN{$$)xv|i@S>+Yz$C&viPIpJDnDgr0Gn|L
zg>wSr?G2^oZJPC6e%9OktT%a?HqhKUMPL=4^A{cRlpgo*HCZ_>9#B3*iJAeUsz<Nx
zR4bn;Vy5%sp%}-N-D2IEf?0ar=YeNvM<A{w7~lb-Gm3FMfawCOA_$e|LW2Kt)ltKq
zye^f$F~|RspYgsZ^KDkrx*CufW=ZTD-+M<LM2HR|hb&gMD*~#gKVH*oP`%KpT4G}R
z6ICCc{#pM}s9cjV3f;Zy!$i%@L@NStwiEHUYX*0;;dE%5M41K)r5ys;U5}Ey)@k3R
zB)-o`ew%7ql>mCY2?AYq1Svm`<T=A%s7>-80KHakyt-Sbe6EUXQ7ASa7<QZg#Q&de
zsn->>TW9@i19^|J%EXI+Z-Rt<@Wd<FyTN3YdjR%-JnoVJ{hN&|+*HJDY1MDchApG^
z6%&AI4kVEF!(+cfah<L{5veS29Mu1PCUv)7*%qT1O;PQ(ns%H2r2qVMOJ|GamR}C5
zh6U9J3KM<?e3Okjfx<bX4A&T>12EO)$i?y;s9hV2w<(iv#>H(Jw43po1uoz{THMh@
zXQb*YuPEoMl@v*qKOi&r8sfUOu`P1NdZq4DtLal0U_Uxq|5U7BS8+?u`Q7utv|%OE
zQ-Ew)j3yHf`syxI>!bBGWKM%t@2Fu<UZr!^MbR5_`zz3H8TB@`5{e<adeaX3n11w^
z9)@KFFw4RL@2JP1>eR%x$I7<r4WFJ{J`WZ->am{kvVM(7JOO_a$=pm<ZQlg!*0`$z
z);EOcGt9Vaa-EMpi=5)9VNYfs@Q@yZv-f*c`rwBH!xso7C}vfo{-vhkecipS(wncu
zv1yk8=SbrU_C!+Lh($AKQuP@%J$k@X?+z7z9I4nDfB12%R&^8}f8r1Rjp2-qRPA;F
zz>|XSN$hVa8k9!ssgz%qT5tgV%>7qlPIwBOJZ{3mI=liGh(sv=DI#f+&X^NKk2ClK
ztZ14Gpxc~QbH}Z!5wpskGkZ<yo_Ik0+8rtTI99bYS^II~QS>2%#tokME$S(ry_u@|
zPz>moh^_(Rp9E%7x)PyDK%10sz>Lpz_K><Eq7Qo}pGQ|+_L~R;_;y36d1FZ1RHe>|
z<>{A0DWJ2p8H0E%MKzqH9x|(YOsW_0fOyy)zq>p6V0WVG)97uUD@^Kg#e53c6iV8#
z#C|9R_@8znQs~aj6cm|p8A_x!ivifJ?1Ns>$GpUDUWPONY2PE;P=Kj<5zkzqMK6h!
zofMXxy#06w`i>?O6(cFCp=9lFvbxuzePIOf|2$Q-J5us-sAzZS7W2S0w$rtoOMz_>
zBwM`n!!3aS>0je0N3rRGf^>dy67EKNI3R<uToAlN2+2{n_$XX;5>e=mfO6YPHgB4Y
zi%M1E4}MrDFD7VO8A((OU)T0q^#e(|o+SNq6M)a>i94UiDn5^t{yJ1bv!BuJhu=8w
z-+?8r8)e(K0R0c=8yw+KSTa6Ea#@zaFU{tcLb);R)2lNq>M&e%6d^tC8F%Cw6!Ru6
zWi!<}DipI^kpwq1@1!pj(`St9Ptx|74KK{`U1nX20l??C@$z5$^LJX)X0iYi#7>cR
zDTZ^05M6{-FiwPuzKwudDbrTvajfjKWP+=Y_LL6`RDUym^s7cjw1w09?X!a<b`{kB
zFb;a^+ygS;5os3!<4*@pCIP%%7pJ_<6>mMw`p0DP@1sS3A1;LQaa`HXH>{-?3;Zd1
z7%kk%TlNE>CR$19)^KB~G@W@WT>Xs??>OL_T1y~qj6@%&v1j;E3u5WKT<&OPPmXkg
zYkvs1ek~&99NK&?bVLt0J-)*dl#ux!JJSE&pZWVx;ji6*-RG$JL%v~EEv%=<3ce2t
z`5R2{3HUab&b(O=U1-M0jlQC2Hx&OkAQLvBBS-L*F)C}0FI<Qc&5Oj2R`%p_Rf6cG
zx9R7ggwsCBmm-1RLu&}cLR9EZ%k_T@=l?#CH(&(RaYxM`iqxA4vCm>ngab&j3yO0R
zFfCf~X}8pOlEU>j@M_T+Ecb-JqlP{CX&`O@M|sKOEeeE-QNkq|zz@F-H#H`uM!R|H
zPoYv__yG;z9kufaFL<Qihw}e9Ui|)Xg5@WGEl2A+CAuw>_*O(z=$A0sQ9sHNz%J7V
znsPWdE0wpDaDGCNkO_+a2EWLcG{yppvn1p%M+sNt0RF!YH2gmGJUxOZa`nhT;`-D8
zOuv-8oFo3nWa&Rf^M~}DoQoJoworMuRQEbwa5I=4c>qZ}>Wg;<oWN_mwV9l}n^Bpv
zpIJ$S7|szuCT~VZ&QmDM9M&?Qy&T0`RRFks?tlE-`17SF)s(+nC=JB-=>WgJ*euum
z-ktux)1|+5T5E$tD&fJ7oP+=K(mj3Jv+T_1LmrDt?ha`FRe4Fd-$gKvq3sbxboGxq
z3z#3p$GkX)5%y2C8E1V)vAFCX0XuqCDX}G}*3;rQi&I}e%-wFe?Z{+L?l#19X%%fs
zd6QiFNGKZ60d~!k;K))$Xk{QN*O!9+;zD_BQfpqW;w!I(7|u4Rf8cx*#``vuehiI2
zfTSG8@J|DJ8^c8`|1d&)2=*9-nIw`ke*{F`iXwW=5NEUMHgc1;s<Pibt%UOL)G6B3
zvR0M6Ng;nEjCz>{$ne$P!4;_RTYjV)Fl^9&UCv>vS_<<uXZ+`6tPdrC^9ssQG~+m$
zc-WtG*pGHRH0m74|0hxQangLsvnM2Cm`F}P2biQ*q{3B=V$G~s&oph6Uw`ws7|Opx
zANO1r+op+aj8Qz1h^F-bTSZqfm45hKBq0k$#{AbMD^}86SYYu8ofXlxivaxw<9HDB
z>kyh-0O_C)>+5jgPb{ci%DyWc`wVi$ZwQOC|6b^h7vNVDD-xkSgw_l(YpJ^RBFk0{
z;Ee7*nbs(YeyWOjs)-vgNXKGnP+R3b*gP+6t`9NsVo>0JUPuV!b>A*a^CwR5DDMjZ
z{VMGkhISmoIv#*O;6*x$7XA##z{I~@GJT8azy$Y&g_*uZ4G;h^wj9M=l?zw3lC>n2
zEyuKZCj-hY?SfzOdEbPK=o`M+t{C1-D&Y55`CiyO6h7ORB0J$}IOCfgDHy1(EFg17
zdDM4B0RHx{VV=O)3jx-}i|C4?9tnWj6*ynH<KZ_D7J9?os}g~kXOW?pWdVITn!Tco
zS~DqZ*L9mEfH|T(Ff!94NbwB{`#)D}*wptmfQoSaa!3(|VTDDCj{&~!?cCPP>ICUX
zhCOqVTu_ulfK0+aO^(NCVqsjI6U=T1|K%kp+Z8@zRmffwa%|CDo0zv21&HL$dpU2O
zRc-e^-5qZK(EB(K35dE$6V>>gr}k^l>*vr#e#Au3&T_QAdq=;VD3N^^f^$LAj`&j#
z0lol=&v8-+De_Cq2qzeB-&K~=MMn*L@)DP}%4e)aacp9)O(9&90M0Qs%G0;%%inc2
z><m8tG}c~82JEc#i|FfTee4a=EezFsKEQMqFj+WS|8&PVs)^<tM-yC8cK)mr|5h*d
zkn)R6`Bjnp3O9V82Ydg;oF8D08usL64rPT$UlaW65u^f}9B^8=UYNR3mH+x#^>**G
z55sNEpdPgj6IpOIC<lp8JRcB$)~^UdhuU&n`B-Tfh!r!B_!3=_oUei<-vRn(-dCZ#
zZzI(RvE+2vjc+^}5hzCud-4jKY`@m{Oq-CiF6G;#0w~6oYgxaYz14X8T}Q)*f!0^|
b0Fy;?aF~6jwp_(puZHEK@HM=Dn_mAPd6Er%
literal 0
HcmV?d00001
diff --git a/milena/doc/tutorial/figures/extend-2.ppm b/milena/doc/tutorial/figures/extend-2.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..6e44be099697121a6daa526889b2662ab230816e
GIT binary patch
literal 16546
zcmeHuS5RBYw)TCVy6McdG2n#51kZTzc<gb+l0YH~kx|ZBLMQ^t0)YeqW3ovmJAsV}
z2HPY9Cg*IEK?JA47<*>UIk)c1|7(t4RJGe@Ts61u(^Tz;uGQaOy}n-Ey;d)61)cfq
zh>JHz%#kyqIBXZD+65yJal{Olldj*pxbUN*q!&({ko+cb70KBgSB_K=#c<`yZEtx7
z`G&c>gm4rbhMdKBVTjo-C{7GVB#}mP#8EE(45q}UR3cZqeC;2C@;vt0+0!m(Pk;8q
zk3W9)FaPrY{(SzNfj?*9&l&i?oPnRxqej`Bau}}Khfs&c-bZ7hqmQs?qin_mmpRR0
zOmG<E92OKa!L!L3qg>Vqi!sDv4lx-}%(6wcWDqXLiC5wyS7P}qaXcudi9l&1Q(CFa
zCuB+&mDWX}LNT8%d7UC0p%E)C2Hiu3H28+z_X&o+JI<nwvnUg6`ZSw1`P&1q{5RGt
z+L&z~nDk*fb(l_r>RB}@tR~5tIda`BT8kH0jeIDkA%xIMq_mSL9VCj4U=M`?#eBNt
zxhZ0VNh@~?sPzbF^bM)^4uZZr!K95d>60w#6pQ}b!vxIdB#%ALVUDpFqfF{3gEm41
zShZ+Stf$0mB+E8ar0X`0@gnG0^`V4jEUAM??x0XRX^cK56N>qC$qTb^jD{;e=U3wq
z(BKnN?*m{rPNR-77?TX@B!f0hqf9aYz8j;{$5~9<GeV<`(5NF+GSr57P4v1&xo(MC
zOOmW73fDmFrc$MiA-HxDxsy!pq|gRge~_JEj2doZch4j6zIRZaS0L1?F$!snMw_Bh
z$LaJ525XWA@ZB(#Ho{<yvN$6&+L(<UXhl6!NLP$eR&&&<Sz=8PSrf$2vHm_$+C*cv
zgyK5M6r1A;+yM4K-};#3rAatK!Iqx+ja`FRP(6?xnLI(EPf(~6G}<JMF$vn~eH7{d
znL13Nk5K5Nbk-P!4jpkuB3e+(mgAyU<0Y$cVryIk6!Sj|x7ThM>H@H>cuK*g0OBqf
z6!S63izLbGblLMb&Wf1y+{Am4EP)~)c?Wa`h7DnH!vy>onJ`8Mtg(S;eYZAYAo=oW
ze)iO@;)$DuP(7n$+6aj<fFpN=kRD+Oone5TXw~wTV>oki&a9OAOvYR`3ZZ&f`;d&i
z9+cgeXuB>#d+jB!Q>8zpM$U4ulN9XBB;o5Tk@meG+Kpa;?U=Csu<$`VVU&O$B@v;R
zC(@Wcjea0LVI(7U{94Y`&3q`PA5XPW>k1{b1>hQe!@EOCP|T8owWwgtOIdSb#=L|+
zD*^0ihLbzh(VemfPT%u8?6z|hn;KRP+;@l&_9|KM6Np`%XK<5WNLNsJPbhW(PaGiv
zta>bvb%_<-D&3I9JXM_i^mYN%@`o5)dl0@On9zhF-1iQ95)9C@BxNou*b6cnLH2^2
zv!LKY^-%X9sE!D_6CD5fd1$Y_WGh87LJTW7=`}>e{*)}-N|V|5erVUAf*zv7I)m|D
zA=rU%{4kCH#q<axyG62IMa*EVVLT^w_BLQ;4iy*O@xwLRG6e7NS}$yS5MX7l%Gj$4
z&XSb1B;zbAxT`S&=vef<NZLLW+r`TQ4~O>JORREw<wd{ZAAN>MxYriJRyttc)uKZF
z!7jWf3_pk?4B<iS_@cfDai3H^qEby~CNES0*lo@94i@E?yJ7AiLvOo>wFUxwx2oV<
z<(y?HXGO+am2o#!fOCfIjEej=#N>t_*GJoPfwnvRF(v2xO3!!?5^*ohHs491m|D-^
zM}8rl!Pwp~oQ>Te0l;oh6ge!Fjw%$R%9xpygxTT@sGjGePqyZU>SfB@v*=Q{pcV`s
zidmKkt#aP7gtIE+uPgXtEWk<2J&H+2a(a}iVcqYrgX(`}77Y_|S5J6dcf;KE2(Cr~
z;!9f)zBLH{IE>VWr*$#7eSAQUVQsBl?`&A>Xk2N#zt+>V-qQpfYb7dTQ!icD$@>Uo
zz9Y<V)B}nk{HL2>Ka%Z;VA}TD9t3m07Zmg9l9y)jFo}@!y<hnS|GVyi_fUX5vn2rg
zI1t+&MtVYG4DduF62N+1d2oBNp>n0UcD=i4qo;YjuLWwuvW&N>m#k~${Y0wR8BY6;
zvrr7%5zgD|PIq#*9hFRHceaZk6!YnlmuAT@nV9A3Q+f_v1;bRigM5d<wg+IJgi{6>
zoMC}zNC1dRi+4(`&G%MYYpv}KE1i#4y8ymhl=3%pksCT$ABie*M&SSB9Mn$UJ|ufT
zin-T=Ws7kRhzdL)pMk#hG07`)<PZUy{;g;68NX_TEtkeXk!_gp_CQ=Onb}KWcG1{_
zEH)IgTz_+^{?>BiouvoW*0$f4C=@d%=01-Vuj|E~I0D(hEnglF#c*tnbAVAC;OxCf
z(*^RdRtLp=y5y%6@d$;Gd&0Bg0@`*>Xg~!(-+km8{v?dhgQND4*aJ*%I{^@L7ph9<
zt`{xdEnjJ@T5YafZL5dsSu`o1>p3e*_CqSCv$$xnwGN75IKpYWF0q~9G)H8YOgm~Y
zKrx>#d6O<1r{nWapsru^uSEvbBLTi^^bBdmV0*CCUOcUn#GZ;#K=scSWG|HGFWo9y
ztSnxtwfV6Uidn9|wXPQ|mu9cF-dX8vSnqF!VrUL9>aI&%XO9vzXF{i+vBW_!ACuTp
z<!X0KojZCMANndO;%y$l&RTc>2cDREM8L0&=BIp0i+?Co+pttNW6(cMN|?*Zn9EC_
z&Atr9%+=hUYq&dKbL&~v^{4l4jo&PXV%B?_S6gbH4?Nx+Zo%z#r#resF;A1@rY(l4
zMBQYf7TRksx#J#i2Z5<Zpa<|_uPnmt+$j6r5A8Yxx&ei`?-}&h#)MT3XPg3vQ!^Un
zq*^nn)jdr%FJz@I<X(a5nX9Upy;(YYqkOtBce1o#zNQ3<v9{LC<X%~*DrrbcA~+yu
zj&LaEX-eF5vSB*e=EvV*SBb#fhWXur`Hv8BuaYCSt^(p?tvkBj16_{}`?XeUyGP6k
z02$PnR5lu;oYrV(P4Tm4^Rtu`s8!FdX3bp99?!^}Ex)>4Q)F!ctks!oS!0(?bH%wD
zB!#>OZhN45rcz?3Ec&Tr-IV2bP8gf-st^GUNX(=y6HAVGlLzo!EdpH&_iYHq{k<jW
zbynn>29Q4t2xMdO=xLR%BSQaxZK&lMp;q<9TE<gTmu}`*8*i+&++JwB3B|NZB=uzO
z)a{b6zqr{h0?d6#C}t{2KbfSRu;?btzvH`VWY8UC&?C=)XH@J@mm{|G0qpAG==*RV
z+a>+KJJa4(DCQ#oD|3(+IWCEA=V%_%)fE_t83xGcZi#erW%+9lZ>=_0t+d=-Xu1ov
z{JJ;p*|nVHP$t;{W_xT0CKNM~7(1S*8#C)BOloMay`;`7q{ai>D;<e|=f>CKqt3
z)FJ%qV7@occ>mm-@=KL!iVN`Fm_Xb{mbXxpSw7MF)9lEjfLwGsKV!MBboo)$Qsa%K
zhm}Bf%cU79Xd-1djNt&I+hV~1AA4&*w8t&+6N&mU+hfv0d;hs)J4^bEPs(=ntT^v?
z7v^8%?hnQH(rANpeh-z~MdI~P`Q1!F{-8KcHlWmeS60M1{sXb%Sy>)bPs?R<R;aL?
zse5MBKF?6UssQZPA*E*868kJG{%L0XbXxr6WkAG-YW|qyZMJ-lPsu#)S$5XfcG}dy
z(NJVJiPB3GbP{=;R7E#M(LsuYVuUWik*;i|ueO*TH+Q{o8MMo;oDI(o6j!hfQzp}9
zp)mmt$Q-((RC77;Pi^cn;%74Ar&9kAyPaHx?NrP<j<Q|)?!Ynk-~itZQ0dKKtWJ`s
zn<8q$%hNA$pzOGZgQ9=nq=Y6uPRXCIDxL;aTDnNgxO0Tua7C{^G48k*@$*YiJw1Be
zvs}|mR{Tt+jh%5SEdh%8bjjPCnE42L&Uc=r=lrV?fps21(05yd2yIwaFM-=b<eR?_
zmV6lk#c+=J-XSR(4S91_#dFnVBRT0%%z`>valj+?M`D*DRba~}cLUfBnRHWWaWh%Q
z>Gar{^thRHz-bKC{4vSfyy#gGBj==F`8jkgGNj%UV0lL{zK_Ii3SsMx1#+Cd1R!>;
zJn?*fX7`nX$(!ZV71t)S)1V`66=kM=<-vCLY*HqQj`(u-0y2}al-R)p{b0O)BuPJJ
zF-%_hL+rNmqMwPFxhMV0-Tv`Yf){|@D23BTi!r%|@V_DucY6uH0Ms|0CK(rR7WC#7
z&)h1TNlmtzO;C34AKa>j1>io1*9dgcU!i#iP*BWdM%-9>+-RzCC`tb$&i4FH1h>~v
zhYGxBOU7X6_Mq_1M8%r|jeYNjb^|K74IMlX8a_s)J|f~P0|2KzdAA4WP$2&cBK=Ts
zrYC8{49Im~7iMo2W^CUn+`fN(r@8W%Cx9D4<d;4SCj`yOy&#C!85KR92DlM)#v0mn
zx(<!DN27vTYcH`?glfHl@50cJF(EI^vh4yue7x_0Y4!=~4I|9UBW{F}(>$2=8a}ky
z2mNS{Uczrl3fI7)SlvoxE)>&6;=H($_@*>#yQb_-Wx<FNkU8*OP)uh8_kj0(u6#hR
zdYTIG)If4VcY?7^AKNGg_`-hNyB>je5CPZE`!x9kzA%g57RA{2erVUY`F1b_vpVsL
zR{WU7)gA|&+tSl)h7&6M^Ggo};^op*Ycn7ZnIbY)rHVIsY44kE->389jst24EGHP#
z87}`OutOd-VbM%k0QUDM8lS`&TD67;F#zuN_TTXcyamG)p7yFo`M*dKzbyv%uHvkB
zElaqRZhTB<s=vVqzopu1_|PWrhT$FDjpqp?DTzz970;@!K{5Rp+#*}JU6Q+aEyMUj
z=oK$Ot&-t*iRJ{q>c{9)$4sSYClUedI`z7y7)_l_^+@+Sxk`;^a3vg5_=A`2689oe
zyi*FuOH2K^U202Rj5@-VDnBRYeM5m-PTqZq;_TioS1#VTI(4(4p9EOFlQ{YujkkTf
ze6b*}o2z;p3D}#oJ(su#JZjnE!8pxCl4jHd*jY`{s*YIAOi}!LbrRGPdx>pjmYhdt
z9rw6>(Pz^n-6;dGd&Ji0E^wGGLHuu+=J1q=?*Ubm@Lh;PU)<B|l<CUChdv=s=>WgX
zvPAPl&g<ghS50+`y0}S3guNvn+H^-Z$rs*j68Tt?El<{r!~@pSWN!S62J@>%)2jwE
zRKq`)yf4$OL@~-wp=#g(op{kh9^f9zJc`pGl`0=)h98@;4~268#Hn?q=4GnoRbJ-H
zyv!H58CFm|WRk!tIOQwa=Po_$+heqFoZO(c4JK&%<5b;xb%$E{ND(!a7YoIFx@4zF
zx2j;4oc6lo9^CGaD-HzA9?=oSIPAxCf>jcP%2Pps|9%mwe@!ZXVT%1JFa334#>>pa
zH8tS8njx{TeCrvp7a`h<95h?l&IqWUzF19<LG?tZYL1HTOHjRe_{TD_0_CcVQQ+!X
z7b0q6CRh-FT4mT@E*V_WhU3Al5@jkZn6?jK)mnt)xla2kIpKAB(#sU%iUg2pj}z#!
z14#K{B+n84L~WFR2gqrAV%1$b<zrP$vqG_P$FS4%hkW<$ntDw^yLQsI#-Dc|t4ufx
z_zr=v3!ZQRdoz%%a`nUhm)lJeAd9wgg&T^fO|ANc$*>uxeZ~Y}n*0f*-SFryP+W(L
z4@4?690&DXuTkBlSGGneMv_%KEykUuKXgZUcTH!F=9Zlgse%R6`3vKJ1bjmhaRh~P
zL>VqINPA$a^Wh6+*-)#jEZ&Apz7Z3%Y0z%OYUa6sHDGo{6CIJNFFYa~FIG?_nZAHn
z(_@I~(ndGS6>Al`cP++uoq%%yI{L>X?~3$mDsJ&9pIdI2R;)yN3~>Gzp~-~3-n#SD
zx=4LBnNzO?#GMs7XH68jF1NW)yBVjqs+G_Y$<Cg%{a(iJeWm+hnSRXDP=J5C4XO@J
zbX&A+tIqK5vHAT#Aym)DB$i_ymM;+rN8k^_nHx!}t*d}DB<7-k^%WuV1T*H6T<4|F
zBqu|)vG=%155d{H-738BL;j)j1QHapqEY`;UH-cE)@I4oXX5D8bAY<&n1Vf?7&C0v
z3>a0tahh&DU`}=hi{1{GZ;#!5J6Z!B#a^O12#-DT8@q;3#(Ii&D<9wm!M7y#*Axv(
zqjgux&r8iX06XUH3sFbh1rBakVIl1v{_{kl{U{&WlSI-2oiQtj9AohNS&=j+z>Q!^
z%^kC-hD|D46zDOkyJG>-d}p}y?P%rpM9tgrd(ctrC6W6O8W(uN*Qkeh_C|{8O%Wh-
zBRczue-M~RX-b499&J>@0hJ}Lqnp$P5xL(z=`_0Xyw7+Dz%T1U%?m^7hAL%NEKfTh
zOaaxIrw!uKWYtijdeEfqHmaV)0@l*b*v*}ZJ3Hf*??$fMbAh&b&M>Ld1=BHPV=!sm
z9Q~#Q;5*upaG@(VLr`eKr7MxzOa|Z#Vej>bJmevE@i3h5P5l<xiUL$)7VykvTI8Zw
z*+F61sM*SuP<tj46vN4?!6fZalDfyNeG&&?_kOZ+XSn$7VByZ-HK+!A33JaSw!@|D
zbN;PiBx|hn%{74U=wIR}2eD~_{4{=1BJN6BDBw(HIU#ua5R!v%@j<xiD5Ag>5CJ!n
zOdH0y1*IzCJ0Glr2NQHx9ZpaTUDozl^!<st?nM1#Bfy^b<2T-qmcJh^`FXI|o(r^1
zvsJTq!>^q7ZO0PV;$&Ob0C^_oD;!~8ND@9-a$c6sFUjJUK=m+fRS`#6#D2KwAVPZB
zJ?6kADCR|K@<xhfL?~uCBMB~O-cfHTrZ+C8FHzfVGCVQGcA9j}27o=kjFtV|m$%)L
zI-Lo)AwqT9OSTKOi&2~#gvdgyf^j5R^mUkh?}v7&wlbGvVV@)uoV~QiyjY-ICH;G!
zDr8t|D6P+SH<U!LfbvYnUU!|VUphQ2^^AY)asP=#fTwC>l-If9&4-zPn<)Bqr0}mp
z1yFlFU9y#DSWS-0_oe7zv``06*>`~a!9q&2gvOOf)0oFX)n9q>4g-FvZ}!KHlIUYJ
z_B20YUM!uH%b_-eJHWNy`CYygmV63rIu$$&`a<IdOHfSazim(ZYhT8%g9Sf#0d_r9
z^T#A_@(e3#VI4hM@NGcQUtoH7z%Tx3%&Ym41tyF<&RZ1eg5n<rob8S1@L@b<l**dr
z3+E$5b0RTx#4=U9=%}ah$AI|bUP<S|fnR7;6Nm+<;O*wie;dmCwLiB%4v_OeHGfR<
zrck{RAN?rWNZ5lUJE1s70d)ooKJ}XVMq;S`3SKQbf#n|Yg=%}~kL$-#p0aog0^vf0
za8U-BrC){`8xm6@UEKA@P$@8czXssnHXh*#kM!$c-rvWHUf+*5{{R>ZI{L>X+r_#~
zqxf1_MDXV@+Cd-60l?nZ`x~=4S1Xj)lyH80fRG8=clAEuPic&K7H3h&Uy2Ye%K_|u
z?yvuK@^M-iPvq>Djl}h;0hm51c_~}`w~3O!jpPmLIoW41AG7>Z<U1w0=dpsTf$Z=-
zNZLVfyd&TjG>xY=gOhtTB185gE0GYzIRJ=UP3Z7B3T27ITH>>pB6uqbfaUM|?*B6O
zc=16M<=@Yg_~UzZfUndx%5=YWrTzC*$<G~@n!un6c;Kh7_<#xg*K@b@sgJTUBKNs1
zD7o99x{As}%KavcaR_Z&t3+qth?9WIgZPjKXFtOBNlE%iuMsRR>wCaCv!aw(<5g>^
zu^UAx&+q1JH3Kq@E<;qOR?(`IH_D~=gra^OV7ER93@<?hSNM~1yea>jDf+WBWzmT(
zxjBk2Jm#Y~TcAvg^Hm7%>tOmJG=2|~vLC}g4#*)5XR-YK2=PAHeH3PbNY3~ku%4F{
zk*kInt3|h-lek%#_3B{-)V2<tqE#(xQOO$>@_WLFr>TI5R^=I3jtafzL%IS3{F}gD
zXTZOm&t|Kd3-UB4d}n2>H^qPo8|5IHaTrb9?@QY6LpvNCaSG(SqbOS;!gS2NJ1A_3
zNKQKixMeR(g)17xs!6k!VO%e}{NjF*y(J&o?fRI<y69F-bVHQlfkZT=2aHvC5mVuV
z&p{G0QDmqFdkN;>&RMXMrh<I4TkwpCwp9qo>llXvm|q6bT>MCTy;xs{3V&ePYxvNn
z?7G0Q-9Rt+3}SJ%?>TRH0KP6;mI!T&bJY;Fnxb1PG;dY|>eaW&v<6A!Lsis6O-#Q*
zIvP!bj#cJ`&Go?Mco7rM0?u=Ly#K$RiTCGqT`x`bC64nbuk!&n4%#6M?J$OQ*bl$Q
zgLDur{1Fgwh<`a}{2I}Y3G59CF@BBeCjeIOQUr5FE?m({Rufg$Y~#j_bbCuav{TRc
zB%St-Ka0NNjqQx$O{W09t<Cem=A!Uf-W1spz-eZ$({RE&D_qcDRgq8Tj_|0j3IXhF
z3zB&RV+(v(Cl8`Cih97$Uc-mB!12NjH=q8H;47{k6$s263$SLE1oWjy_Odc!)u^yu
z)@>96?uljo;TdiLimy=E|GHSsroOHQM8M1Eg9<SW3oKlG2=L7S)HZv`_I1sSPLPIV
z*kS?62}RilIQ{s?$*~wsG>nULfZ5Eze}2wh!-w`VpRpojuL?QVNUl}PTa5thpp9GE
zFCJBH^*r1eYJ1ajKNksD&l5&!+&AvpFWoPnLKpfF6F@r}I{L>XJ2&)82@=^iK{zKQ
z?SL<JAK<G4@hMI+Az6No8Rh`P?YhWvI1AOb$fd3D8LJT-tC(w52v;S5+S+<q+GbtZ
ztB(5ZfyeJg+bYO_9i4U-efgx9EfKwjp_)$n8BYRkj?mFRCV6)wZbTEwIgBPaqipP0
zM*z`NewHb}D3V{`hVF7>?>?LT9So{%i9=cD(N_ikASe}B<$${ST0zQsW#02gRa-re
z-VC)if$kBtnDG3I0oh1=!fC(QlRkwQI&`d0m%Obo^hb-C2fT^SNX{35l5YSvAl?_j
zysyL62(jdN$d#|$8W1R`{$)1V_N?-mRv~9i%C|}dP>eOlymmcnv*G%y_WC#dEzfQN
qZjMcXA+}nL`6AYGF(e0tujT>j9#GAHO8%UIKWE_28TenBf&UM{f^60R
literal 0
HcmV?d00001
diff --git a/milena/doc/tutorial/figures/extend-3.ppm b/milena/doc/tutorial/figures/extend-3.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..c2ad4ad4d1ce49e5fbb45dceb25d6c92f92bb99c
GIT binary patch
literal 16546
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
literal 0
HcmV?d00001
diff --git a/milena/doc/tutorial/figures/extend-4.ppm b/milena/doc/tutorial/figures/extend-4.ppm
new file mode 100644
index 0000000..5425043
--- /dev/null
+++ b/milena/doc/tutorial/figures/extend-4.ppm
@@ -0,0 +1,7 @@
+P6
+# Generated by Milena 1.0 http://olena.lrde.epita.fr
+# EPITA Research and Development Laboratory (LRDE)
+64 64
+255
+âyá
tßlÞnâpéwêtÍde¡>W¬HY°KV²KV±KUºSXÄZZË_\Íb`ÍebÌc_ÍdaÐfbÓeaÐeaÏecÐgcÎgeÌggÌd`ËfcÎc_ÐgaÏeaÍfcÌcaÊcbÊbaÊabÈaa¿[a±QYÁZZØzoÝqÜ~jÝnÞmÞhÞgÝjÝnç¢zùÑ鎩NZžY]Œ\]»^bÁ\]Â^_Â]^Ã`bÃ_^¿Z^ÇniâmâlâkàiånêréjÌ_Z¢;PCR³IS²HQ²HPºQVÄY\Ê^ZÍ_[Íb_Ïc_Ïc]Ðd`Ód_Ñd_ÑdaÐcaÐcaÏdaÎa^Íd`Îb\ÐeaÏc_Îc_Íb`Ë`^Ë`_Ë`_Ê`_Â[`¶RZ²NYÑnkßsàoá
mâ
láiàhÞiÛkÛmõÃúÑÄtg³RY»Z]Ÿ[]¿[]Á\]Ä]]Æ_^Éb`¡DR_AámãkâlánæqçoåkÌb_¡<N¯BNŽIR±GP²FNŒPTÄXYÊ\YÎ`]Ïb]Ðb_Ïb`Ñc^Òc`Òc`Òb^ÒcaÑb`ÐbaÏcaÎc`Îa]ÑgdÏebÎcaÍb^Ía_Ì^]Í`_Í_^Ã]aŒU\°LXÃ`dÛ~sâvãqäpâ
mâlÞjÛ~lÙ}kåuúÑSY¹V[¿Z\¿]^À_aÆbbÏfb?P[B]?âmå
lã
oårçrâoæ
jÎ_W¡8J®BN³HR±HPŽHP»NRÅXXÉ\ZÍ^[Í`]Ï_^ÎaaÑa^Ña_Ó_]ÑaaÒdcÐ\ZÎZWÎ]\Ì][Ë^\Î``ÏcbÏcbÌ_]Ì_^Ì^\Í]\Í_^Å\`ŸV]ŽMXÁ\fÙzuâwâtáoâjálßmÝnÚ~lØzióŒûÖ ÒpŽRWŸ[\À\\À]_Écb<O\B\<d?ã
nänæséqçlãlæ
iÎ^U¡8JBO²GP°FO²EP»OTÄVXÇZZË][Í_]Î][Î__Ò_^Ï``ÐacÑ_^Ò``Ð[ZÊYYÊZXÊZYÇZYË^_ÌacÍceÌ__Î_^Ì]]Í\]Í]]É[_ÀU\·MYÂXbÖspÞtà
tß
oàlànànßmÜ~nØyißjùÒ÷О_bºSWÀ\]Æbb<OZBaEd@b>äpåpèpæfçhånçjÌ]V6JBO³FP±FO²FNŒNTÆWWÇZYË[YË\]Î\\Ð]`Ð]^Ð__Ñ_aÑ]^Ñ__Ð]^ÌacÈikÈqqÅmlÆ]^È\^Ë]`Ì]`Í`cÎ]`Í]]Î]\ÈY]¿S\¹NZÂU_ÔolÚyqÝtßoßnàkálß}jÚxiÙueÖraðŽúÚ§á€~°NV»X]=NZ>^BeD`?]<æoéqåeÞn[ågæoèkÐ^V6H¬>M³FQ±FN·GNÀOTÊVWËYXÎ\YÎ\\Ñ^^Ó^_Ò\^Ð^^Ò^^ÍbhÈu}Ã{ÈÍÒŠÐ¥ÓªÏÆssÄW\É_dÍ^cÍ\_Ì[]ÈW\¿R[·MYÀT]Öni×tmÚyqÞqÞ}mß}jà{gÝveØre×pbÖqbÝjøÎûØ¥Éwh;MX>]?cCaB]=_;épêm×eVÑ]VçjémêkÑ^V1G¥<MAN°CLŽFOŸMTÇTUÉXYÍYXÍ[ZÑ[\Ð]^ÏcfÈntÀbm¿kuÁpvÆz}ÈÌÏÒ¥Ö¬Ù² Þ¹šÑŸ_hÄX`ÇX^ÈW\ÂSYŒNWŽIUÃS[ÙoiÚtkÚvoÛyrÞ{lÜueÜscÛscÙpcØnaÙo`×oaë¡}ý۬݀W>Z?dBaA^A]?`;ísäzc®?IÊYTèiêmêjÑ\S.E 9KªAO¬CO°EQžJRÂPUÄSVÈXZÌZ[ÏYYÐd]ŒS\œ[b»]f¿ioœiqÂnsÃx|Ê
Òէ׬۳¡Ý¶€ÝŒ¬Ø³Šœos¶MWŸPX¿QYžMY²GTÁQ[ÝqjßxlÙsmÖplÚtkÛsgÜpbÝsdÚqcÙpdÚreÚsfÜzkó¹~9LV>bAdB^@^@`?X9ëoÌZT1FÊZVêjëqégÎ[T-D¢;MªCS¬CQ®DP¶KTÀQXÂRVÈUXËWYÒ\[ÆZY»NVœU\Á^dÁchÄjmÃlqÅsvÉ~Ïקگ܎£Þ¹©Ü¹§Ú»°àĹʪJWŽKV²GU¯FVŸP]ßumä~oÞvlË]`Ë]_ÝujßqdßseÜpcÜqeÝsfßviázj0IW=`?d>^>`C_Dd F?Uàr`š;J5HÊ[WéiëoèiÍYS/F€;M¬APER¯DR¶KTÀQUÄTXÉWYÊXYËWX»LSœS\ŸX_ŸZaŸ^dÄhlÆknÆprÌxxÓکܯ ثَ¬à·åË¿æÌŸëÔÅÉ¡<MªCS§AT»O[Þsjä}láynÁTY3JÓffßshàreÝpeÞqgßqfäxk€FSW;`?dA]>c@\Dm+R<XÏ}u¿LM8J6GÉZWç
jëpè
hÌXS0H£=O¬AQDQ¯EQ·JRÀQVÅTWÉWYÉYY»LSºOYŸU\¹T\»X`ÃbfÉlmËppÍssÍwvÔ×Ó Þº±åÈœâŹâÄžãÈŒåÍÁëØÊ±qw7K<PºMXßtlå}názpÄZ`n=±IVÝqjàrgÝoeßqhâshÎc`^A_?gA^?cA]@f$MCeÄwxË|u8J£:J 7JÇXUçjétè
lËZW/F£<M«BQ¬CO°EP·JQÁRVÄTWÊZ[ÀRXŒPX»PXœT[ŒX_ÂafÆhlËnoÍqpÉmoÌssÎ~Ò໯âÀ³á¿ŽÞŒ²áÄžâÄžâÈœäÌÀæÑĶ-D¶ITÞtkä}pâ|rÆY\h>~$BÍ]_ásgÝmcàqiãtiz#CY<iCd@b@`@bFw3YŸqxÉ~zÕ~ :K¢<L9KÆYXålèrç
nË[Y0J¡:L«AODQ®DP·JRÀQW¿QWÒnbŽEPºNVœOVŸT[Á[aÈglÌooÊmoËmpÁcjÃrw؀ീ޵§Û³šÞ¹¯âÞãÄ¹âÆºâǺáÈŒäÎÁé×ÇXhBNÝqgä}oâ{rÇZ^n?_73FÔjdÚtjáti§FRY=d?gA`AaAbAd J·kwÄvwÑ~Õ<M:K5GÃVVælèrç
oË\Z.H8K©>M©AOETµJTœMT¿V\Özi³FTŒMVŸNVÁU]ÈaeËilÊijÉijº[fÅx}ݚܧ۪۫à¹ß»¯àŸ³ÞÀ·ßžßùáÈœáÊÀåÑÅל³9LÛphã|mã|qÆ[^l@X8MfÞœ°åÊŸæÅ·_F]BgCdDbBcB]@¢XnÈxyÏÔ~Ô{;L¥=L€:IÄTTæjêrè
mÊYV+E6J¬@N¯BM°CN¶HQœOUÑ{oÐj_°ESŒMUŸOWÅ\bÅ]bÂ_dÉcdœX_ÏÜØÙ¡Ú€Ý±¥Ü±ŠÝŽªÜµ¬àŒ³á¿ŽàÀµÞÞàÈŸßÈÀåÓɵpvØnfånâ}nÀWY\<rÙ·«æÌ¿êÑÂðÚÉxIf]AeA`>]?dC:\Ë{|Í}Õ}Ô}Ó{©@M¬BN¬>KÇUSåkêsênÌ]Y/E¢:K¯BN³DNŽDN»KQŸMSàyÈ\W¯DQ·IUÁTYÄW^Ä[dÈbfŸYaÓ~y×ÖÛÜ¥Û§Ú©Ø£Û«¡Þީ߹¯ßŒ±Þœ°Ù²©ÝÀ·ÞĺÞÅŒÜÅ¿Ûwå}eÞwd¶^eÀÛ»°åÊŒãÆžâÆºïØÈ~Mf_Ca?_=d?_CÂq{Í~~Ö~Ô|Ó|Ó{COBM®ALÎXRækërìqÏ`X/D£;L¯CN±CM²BKžHNµFPç{ÈYW³FTŽER»MVÄV^ÅX_À[dÒvsÓ|xÍ{{ØÚØÚ¢×ڡ܊ۚܯ¥Ü±š×©Ø²šÛŒ³Üº²Ú»Ž×¹²Ý±Šâ}iÝß»ªÞÀ³âǹàöâÄ·æÌÀîØÆi3V_C_>^=fBKeÐ|}ÔÕ~Ô{Ò|ÒzBO¬AM°AKËXSèkîsîsÑ`X.C¥:I®AL¯@L¯ALµEM±@NôŽ
Õh]ºLS·HTŸMVÅV^ÃXbÑstÒtrËpqÔ~}ÕØØ×ÛÛÙÚ€Ú© Ù§Ø®§Ø³«Ù®ŠÖ©£ÕŠÏ¥¡×Žªßµ€ßŒ¬ãÃŽá¶ßÀ³âĹߺ®åÈœä˺WA`A\>c@1YÍv|ÐÖÕÓ~Ò|Ñ{ªANª@M¬@KÈXTèjítìsÐaY0G¥<K¯AN¯AL°@K³DM²EPõŽßzeÏ]X¶EQ»MWŸR]ÐkmÏqqÇhkÔzwÑyzÑ{|Õ
ÚÚÚÛØ××ـة¢×¥×€¡ÓÑٮܶšáÀ²àŸ°ÞŸ²ßÀŽá÷໮ÔÚ©³Y@_?]<fJ¯]pÐ|}Ô×ÕÓ~Ó}Ô{š@M§>Jª>LÌZWèkëuìqÑcZ0G¥<LAM®@K¯AK±BK±KTô¯{ågØi]ºJSºLWÏjlÊgjÃbiÓrqÎpqÍvwÓz{××
ÖרÔ
ÕØØÖÔÏסݮບߌ«Ýž¬Ý»¯àÁ¶àÞäÈŒÔÎØzC]\?\?aA>bÏ{|ÑÔÓ~ÒÒ}Ò|Ò|ªAN©@N³CMÑ[WékìtípÒe\.C¢;L¬?M?K¯@K¯?I³QW÷ºémáz`ÈVVÉ_cÇciÁ_hÑmnËjmÈiqÎruÓx|¿k}µd~¯fŸvžn~ÏÍÏŒvÆÏÜ¥àŽ€áº§ÚŽ¥Û¹®ÞŸ±á¶âùãǻ޶©»oo±\fÒ§T<^AbCeJ»huÐ||ÕÔ~Ò}Ò}Ñ{Ð|Ð
{¬CPªCP·ENÖ^VêkítîqÕf[-D¡9J¬@M°AM±?K²?H°FOøÀð¢sÙkXÈ[YÀW_ºXdÏikÈeiÆcjÉgmÏouŸez¶`y¢Mo
>p²tQ~Dy?nh$Q_$SŠl|Ø á¶Šß¹©Þº«Úž«ÞŸ±àÀ³ãĶ߻®ÆšQW£GWÖSb\>\>a?~5YÍy|ÒÔÔÒÐÏ|Î
|Ðy°FR®BMžDNÖ^UélìsíqÔfZ/E£:J¬@K¯AL°@L°>I¥6Gò¹ó©xÒf`ÍhgµP]ÍeiÅbjÆ`hÇdlÎinŒ\rº]wHu}4dm$YN}=t}Atg/bRHŠjtÓݰݷ©ÜހܶšÚž«ÝŒ±Þ»Æ¡FT£GVÀjmÝKZ]>a>`?_H¯`pÍ~}ÕÕÓÑÏÐ}Î}Î}²IU°EQ¶CKÓ]VékësípÖh[.E¢9J«>L®ALAL±AJª=IØwöŽÜoÅ__É`hÄ^fÂ[gÄ^hÃbnÀ]mŠNjw0ak(X_Hy7js,\~Dyh.ck8hµnsÖ Ú¬×« Ö«ØÜޥܹ«º
Sj¡b|Ö{åyè¢O\]=d@`>c>r+SÊwzÓÖÕÓÑÏÎÍÌ}ŽKU°FR±AKÎWRémìuîrØh],E 7Iª>L®?K¯?KŽCL¶FLŽRVôœè{Ã[]Å_iÀZgÀ^sÃ]s¿[m8_x5ee#Us2c[Go)Wj Qm.dwI{`أݎ¥ÔªÔšÒ£Ô¢Û°¥Û7UOn¢d~Òä?N\:e>eA^<cCNfÃtxØÕÕÔÒÐÏÌÌ}ŽJU±FQ¬?KÆSQçmìvïsØi],D5Hª?M?L®@LµDNœLR°CLàîªÈ^`¹TcÀ[lÃ]lžXr=er'Y|6g`Ou2fh#Q`Df"Pu2eSœÙ©Ó¥Ñ¢Ò¢Ò£â°šë³©ìާÂ[b8YUsÅ},FZ=g>jBa=a;l$M°epÄ}|ÖÔÔÔÒÑÐÎ~Ì|°IV¯FRª>JÁRTæoìwîvÙk`-E8L¬@O°BP°@M¶FPÀNUºHOÞàr»PYŒVcÅYfÄZh
0Qo&RZCl(Zl*[h']|@qZBe#Iª[sŽ~ةج ÌÒ¡Øè¬¡í¹¬î¹ñœ¯ÚyusB5ZÂ~iA`=i@l"E^;`=B^ºpsÊ|ÒÔÓÔÔÑÑÐ~Î{±HR¯EP©?LÀRTænìxîu×la1J¡8K¯CR±ER±BO»LTÄUXÃOSÌnh×~n¿QXÆ[džRd|)OeFi&ReK_Gf Rz:pt:jXA»gnÙÃÑ¥¡Ó¢Ñßè첊î»ñÀ²ôÆ·ë'BdEžwl#IfAk Ej C_<_B®dnÆ}xÎÉ}É}Ì}Î~ÑÐÐÐ|Ï{±FRCOš=J¿PSæqëxíuÖlb1L¡<PCR³FR³DQŒLTÄQVÄRUÆUVÌg]Í]eŒ_v.Rh'YZFj%Ug!NcMdNl+^c'UZgÕÛ¥ÅÔŠ Ôà
çêí³Šîº«ñÀ°ôÇžñµŠ¬>NW?®i|u'KgDk$FdAb>t-RÀstÏÑÎÍÊ}Á}Á|Ä~É{Ì|Ðy°DOANª>KŸPUäsìzíwØk_0J :O®DS±ES³DQŒKQÈSUÎ^^·ZXšNY¿f~£AXl.`k2e[Co*X\Be!Oh%Z`!QE[Ì
Ø×€ÒŠ»ejÊhpÜéëíªí²£ï¹šóÁ°ï² §>PX<Vo:Yk%Jm&Ha@_APgÀtuÓ~ÑÐ}ÑÐÉ}Ã}À~Ÿ||¿z{Äzx¯DR¯FQ«>KœMRæ
qíyïzÙna1L¡;O¯DS±CP²BM¹HPÅTYÙrk€S\Bb§IWw._l-cu<n\Ja"OdJ_Fj+[s.OÊ|ÞšÕÑËceËchÂYb¢8MÂ[eæìí® ìšÌwtMZ¡8Jb=EcKcm%Hh Db@fG²frÈ}xÕ|Ñ|Ð{Î}Ï|Ë{É}ÈÃŒ}Žrz«BOª@N£9HžHOæ
nîvîxÚoa/F¡7I°BN±?J®<I¿ai×|nÞ{nœcf{,Nl/a{@vDz]Ok,\V@p4daDU=¶inÝ๫É)Aw<o>~1N.JÒZaßpsìñž§²`g,JuAu?c;
<\¢Xln%Ic>b?r*O¿rtÐzÒzÐyÑyÏzÏzÌyÉ|ÇÁ~»{~µv|ªBOŠ>M4F±DLænîyî{Úm_1Fš;K³BL²CM¢7G¯cjÜœ`by*Mj+^i([h*aR
XC\Gh%P\>XA9YÌܯ¢Ö©¯IU}?9T9^ß·¹²J\ÇMWÛdjíÛ2SFiWjg7^;8Z©bts+La=_?JaÆyvÒ{ÐzÏxÏxÏxÏyËxÅ{À}|žvz°qx·|}®EQš?M2F¯ALænï{ð|Ýqb¢6H±ALœJR:ILfÂy°vyk.^r8ng*]l0fy@x]h*YY=`A\=]AŸrwÛ€Ò¥Ç[bÖfmÊ`kÄWhÈrØØu{ÑW`Ø_gí§¡ÛÃfxœm9N|>aA}4X¯l|t+L_=fB¯dnÉzÐzÍxÌyÍ}ÌzÌxÆ}v¿xwžux¿zÔ⬫BO9K,B§;Häpï {ò¡ßta£4E°@J¿IOÄak·dz|:eb Ph*b
Uk0df(_{HSm5a[?]?U@IWÕÓš¶HRÕ`ißx}á~Þ{~Ü{ÞÜ~×clÙZeéèž°Û|Ñak¹JV,Bf=v,S¹wn#E`<o%GŒorÎ|Î
zÌyËzÊxÈyÆ}wŸyv·suÑæ³
èŽè³
:M2H&@¢8Hãoî{ñ |Þta¡3D®?NÀXl¶gVt9il+`OK~VEb$WzCwxHwJdaDWAi*OÄsuÛ²=PÅKTØ`gâwzçèçæà~~ÜkqÚZcæëÀ¶ßÛioÑYc3IlAp"IÄe<_;>VÃvtÐ|Í
{Ê|ÉzÇxÃ}y¿yw·stÒìºì¹
éŽéž/H,E#A5Gâpì{ï|ßsb4FªAQŸLWOy
Ex}9kl2iTi+\\DZDa"Jb>šYjw3PO; MZØ¢cm#BËPXÙ^cápræêéçáyvÝkmØ[`ãíÄ»Þ
ÜotÔ[d+Ek@lCÉ
d@e>«X_Ì{ÏyÌ{ÊyÆzÄ~xÁ|x¹tuÆxì¶ížìºëÀëÄ/K-KvB3Gâoê{îwßqa.E°Rlžb@jRo5is>z`r9h`IT=~.K~,Q»ow>Q_@ÂpsÄW<'BÇLTÙ]aákoå|{èéçÞom×`dÔV[ßv|ðÈ¿ÝÛlsÏY`qCr"Cg?Áyr-LfAÀnkÑyÑwÌ
yÉzÄyÂ|wœxv¹ssãª~ïží¹îÅîÊ¡ìÄ2K-Ht<-Bâoì|ðyás_1I®Lg²Vw7hF{p3ns?wao7i\HY?:V¥O\x.JV<¥[eÇq1K]<1FÄJRØ[_àfjãstä{yæ~ä{ÖbeØ^cØ]bÝmqòƹÜ|ÙjpžLY[?u%Df;µlx
?Wy/LËxnÐzÍ
wËvÈyÅyÂ}w»tsÌxïºïžïÄîÈìÈìÉ¥2I,D!>£;Lâqë}ð|àuf 9R©>N°Lj5gFwo;ql1jUa\Ek#DWD~=a[>x9UÚ `hX7d> :LÈKOÙX[àcgãqrãvvä~{ãzÙfjÐTX¿HQÑTZè ÛxxÕfk
.KZCx%Bk;¢]oI^LYÏrÎzËxÉyÆyÄ~vÂ{u¹rsá¢|ðºðÀîÇíÊ¡ìËŠìÊŠ/E,D
&A·R^ãwêyð}áxf3HŠ<M»Vop)]r3in4er6pTco3`K\YG|9^°m}¬\e±{}YBf"FeB§EUÌOUØX[Þ`eálmârtä{{ä}àywÝilá{yâå ÚtxÁYc\E_F0Ip>JbSeŒgdÐtÍzËxÇyÆyÃ~x¿zuŒuqë°~ðœ
ñÈîÈïË íÌ¥í˪)B&@#?µUbãxëyð|áye2DªBZŽXty1gv;ic'Ym/bv=r|F}\}3Uy/Q¶tÁ¥Xbh&Fd<p!?d<¢FXÊLSÙY[Þ`cáhjáijârrávuÝutÞzyꬡ鯊äÖnu8SZDf F
/Gr<6T®cnÎsdÏvË
zÈxÅzÃ}wÂ}wŸxqÂzqï·~ñÅñÉïÉîË¡íΫîÍ®x?#@#?³Saâ{ë}ð}âye5N¬Kd°Rmj([i+[d(]zDz{Awr9p
WDnÃÑ£«W`y>Vl@b:t#Ai<>RŸBLÙZZÝ]\áfgàjhËSVÎWYÔ]^ÑZ[Ú`a×imÎahÇcm_D]Cn#E1Gv!>r(LŸorÒyfÎxËxÇxÄyÃxÂ|vœvrÅ}pñœòÌñËïËîÍšíЮîÏm@z ?(D¶Xdãxì|ï|Üyv¬OjšD`§Nop/^ZJn2i[w@zKw?s³eÙºnn¢dj^B_;f<p @mA4Kš9HÏRSÕWYÜ`báomÝbbÖPWßR]âjzæ~ãx×nr9Q]A]>p A3Iz(DkFÌ~yÓ~nÍxÊyÉyÃxÁyÂ~wºurËrôÉñÍ ñÍ¡ïÎ¥ïЪïÏšðÌ£g>p:)CŽQ[â
uì}ï Þ|s,H¯Vr8^z@i_#Uj.fiWwC{akÎÇq`#KdE`AdBm!Bn B~/I+C»DKÊPTÖ[^ÜfiÞijÚ^aØZ]ÚXbÝ_mÛnw¿]c]A^Af@t"A3I+Em!HÑ|ÐsËxÉ{ÊyÄ
{ÁyŒ|xµrpËvöÑ£òТòÑ©ñÑšïËîÉïÉb=d=8L»T[àpì|ï~àyi-H¥Mm{3_m.X`&W]VihWSR}Ço/N[EgBaAc@g@o?n?x$@.@»DLÒW\ØcgÛimÝnràvxäãÚwx-HVBbDi@v$D6J
-Dq EÒËsÊ{Æ}Ç|Ã}œ|ž|xoqÈ{öÖšóÑ€óÐ¥ñÏ€ñÍ¡ñËòÉ_?\?4IŸVZáqë{î|ázf.G>[f$Sp3]e'WYRXo9qhh¥^D_\!K]Fo"Dd@bA`>k?l@p"Av=";¹DLÎY`×inÞvxåæãÌjncCY Kg$Gf?{,I:N0Fu$GÒÅvÆ{Ã~ÁÀ|¹~{ŽyxšmpÑö×§óÎôÑ€óÎ òÆíºÓt_@X={&B²LTárê{í{Ûte€YmVsa#Ql(Tf$QTKhw?t}I}^{šed1\YF{)Fc@_@b?b?l!Bm A(A0H©CT»S_Æai×ouÞ~~ßÛÈ{zn7YZ#Md!GaA|.J?T6L,LÐ|®^`Žefµor¹xwŒ|ž|{¯vw£fnä¶öÐôÌõÊðŸÊly.Ed=8ShAq>5GÞzlé{ë~ßI]}>_SEq-Wf%Sm+ZxEwWYV[Spb)Sy'Fg"F_Ca@a@hBkAz%B¹LWÍ[`Î_dÓhkÙnpØrrØtsàçŽèŒ§»wA^U?{-J=T3K3QË}užjjŽbd¬Zb€T^£W`€^f€ci\hîŸõÆôÉòÂÉpr#Bs"A5J§uUg/G}#>Útiêzì~Þyj°`ui+NP>}Aoh,_Cp`%XL|PtBybmMrGlm Dh"DaC_CbEfCw'Eq"CŽKUËX]Í^c×hjÙklØlnÜ|wâæ¯é¶îŸ€îì xl$E5N,F8UË|uÂ|vŸvt¹ps±ekŠWaJY¬YZDQí¹öÊôÇÇjx'B/G:L9K¡qXe{"?Úvkë|ìyãu·uYC\De$Nn,Ui)Wj/[k5ee+^p:qXy€S}Xyl/Vf#IeF^Gg#Hk#G7Lr!C¶LWÇW]ÕcgÚijÚkjÛqoàzâä¡ç¬ì·ñŠóÊŽ³m A})D>XÇzrÃy¿|wœyxžtv°lrŠdmŒgYÁg[ôÉ÷Îé²
2I;M>O§IT?Pu5V°°y#AÛxlí~í|änTkQ>_H]G[Iw;gYGe)Ys8kt;q}Le¢ww?hNjb@kA]Ai#Gh?®DO~$A±HUÕ_aÙceÛjhÜkjÝroàuá}ã
æ€ê²ïœ¡òDZôÑœTgl<CWÅyoÄtÁ|tœyvºww³ru®joÆp\ÜnöÐöÌÉ}e7M BRMW BQ£HZXA®¶m=Úxiì{ï|åiOdUC_GXCb$Tp6aaIb$Rf)[{EzzE{ekq5cYteAq%D_AeBo?µFM)BžKUØ]]ÜecÜhdÜkgÞsoßzrà
zâä æ®íŒ£ñƲóΜ۵©]6LXÅ|qÅrÂ|sŒxu·sr°oqŽgfã |ôÂøÒò¿®OP¢?O±NV€DQ¢DRK_O8Š}·m<Úwfí{î¡{æg?Z^HY?UBxBpf*Ta!KYCZIk1d|J~dqpzLnjAn!Be@cB1FÌVW0FŸNTÚaaÝfcÜfbÜhdÝpkÞwoàxáãå«ë¹£ïŲðÌ»ôÓ¿t6QªTXÆuÂ~tÀ{s»wrŽrpjlÇ|n÷Ï÷ÌøÑßhš@JªCNµOU@Q¢L[G]K
+6 uºs%BÙteë|è}ápBeWCZ@`!Le'Rg(Q`!KXC]Mh,Zl8mpOzNq}Bd=_~7Vh@n>²DMÐZ\0GÇTXÚbaÞjfÝfbÜd_ÜkeÝsmß~và|âäšè¶¢íÁ°ðÈžòÏ¿€qyµ_\Ãu¿|s»yqºxrŽsrjkÕt÷Ì÷ÍõÄÌfW°FL°HN©EO¡DSH[>VN
9dx¹z/I×qcìzì{ãoCbXA[Fe%N]Ka"KZI[H_"Qk3dtDycU
x?iaEh Bn$Db>)AÃPTÊZ\3LÒ^^ÝhfÞjfÞhdÛfbÜibÝpjÞzsßzáâ æ²êŸ®ïƶð˜Ԛ¿haŸ}tŸ}vœ|u»zu³tsµolÒ}dî²zøÏëªvÀQQ«CMŠAL;M¢HXCYD\M
8Vož
<QÔl_ëyìzãk PeYD` IWDa"Nb&P_ J[Fc&Sj2cl5dj9el4egcA_<]:e;¢:HÉVW®DP€BQÙdaÝjgàniàjdÝgaÜhbÝojÞwoß~tß|á
ä¬èºšîŶðËœñÌ»ºe_HR§\_³om¶xt¶zvÇ~pÍu_ÙkúÒßb¯DL¢>M4H FVBVFZ7NL6Lg£IZÏg]éxí{æjFc^GW@_ K_!M_"Mc"JXB[Kj5jcv<mz?hf$J];Z:Z8(@ŸMOÅRR(DÇYZÛdaÞjgàlfàleßhaÜf^ÜkbÞrjÞ{oßxàã€æ¶€ìÂŽïÊ»óÏ¿Žps;L6H4G7KGVÀtgÓfç©}öĺTM,C7IASBVDXG]q#A~/GUiÇ©¢\fÌg^èxì¡zÝkEbYD]F\E[Hb#Me$NVBZD^JuDtkO{Z=X:U9i:€<HÇRQ.B¢@MØc\ÜgbÞidßkgàmhàkbÝg`Üi`ÜmdÝwkßsà|ãå¯éŸ®íǹñÌŸÒIU LU<Ns'DV;¬d^é¬róœÖc$@,D;QFX9PMa>Un!?BV¡kyÄš€¢mpÊf^éyí£zÔ|iCaXC[D]FYEb%Pc(S_"Md&Re'Th,\Mzu>fW>V;X8.B®BH*@5FÑZWÙc]ÝhaÞjdßjeàmfàngßkdÜkdÜjaÝrgÞ{nßzáãŠæ·šëĶïÊŒìIJCQ¡PWIT<O|.H·g`ó¿Ð^*A{&A3KHZ3LAXQg9Qr(Fr,IVlŸ¡šuwÈd\ézï€}Üoq*PWC_I^H`$Oj.Zf(Y|Cpe*V_'Tn3eYr8bT>W;c7z#<.DºIOÍXWÓ]Y×b\Ûf_ÞhaßkeànfàsjßohÝmeÝlbÜodÝxlÞwáâ ä° è¿±íÈœðÍŒ¢\cJTQZN\¢Q[¹\\Ârb7K1F3KM^4J1KViNdt*Fm#Cc Bz<[Ê«ŠŸÇe^ëzð€Ìzme"KYD_Ic#Oa&Rm2_] R
Qc)Yl5_r7br;lr:fS<d7->¹GJÇQOÏYVÓ\WÕ_XØ`ZÜe]Ýg`ßiaßkeàpiàrkßrjßqgÝriÞxkÞ~qà}áâšå·©ëÄ·ìÊ»ž~~DQT^¥]eµZZ¶QUªHS¯MU;NCX4J1HM` ]o;Sj!@j=]=n.RØ·«Ò«Çg`êxî¢~ÇunbGZCe%Oo*Tj*Xv>ij(Yv:iw?nt=hg%Qg(Uy@no,R'<³@DÇNMÍVRÑ[UÒ\V×_XÙ`XÝd\Ýd\ßhbàjeáphàpiàsiáwkßvjßznàsá}à
á£ä³£èŸ±ìǺ֊CULWª[`Ä`ZÂXUÍ`XžOR>R
;V;RDX¬gsG\f>i!@9K
\ No newline at end of file
diff --git a/milena/doc/tutorial/figures/extend-5.ppm b/milena/doc/tutorial/figures/extend-5.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..d384c49a159ce39916c48838244da08cac42f724
GIT binary patch
literal 12406
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
literal 0
HcmV?d00001
diff --git a/milena/doc/tutorial/outputs/extend.txt b/milena/doc/tutorial/outputs/extend.txt
new file mode 100644
index 0000000..e69de29
diff --git a/milena/doc/tutorial/samples/Makefile.am b/milena/doc/tutorial/samples/Makefile.am
index f4c4877..899f8a8 100644
--- a/milena/doc/tutorial/samples/Makefile.am
+++ b/milena/doc/tutorial/samples/Makefile.am
@@ -9,6 +9,7 @@ noinst_PROGRAMS = \
domain-display \
dpoint-1 \
estim-sites \
+ extend \
extension-ignore \
fill \
fill-call-1 \
@@ -55,6 +56,7 @@ box2d_bbox_SOURCES = box2d-bbox.cc
domain_display_SOURCES = domain-display.cc
dpoint_1_SOURCES = dpoint-1.cc
estim_sites_SOURCES = estim-sites.cc
+extend_SOURCES = extend.cc
extension_ignore_SOURCES = extension-ignore.cc
fill_SOURCES = fill.cc
fill_call_1_SOURCES = fill-call-1.cc
diff --git a/milena/doc/tutorial/samples/extend.cc b/milena/doc/tutorial/samples/extend.cc
new file mode 100644
index 0000000..2f9ae0d
--- /dev/null
+++ b/milena/doc/tutorial/samples/extend.cc
@@ -0,0 +1,94 @@
+#include <mln/essential/2d.hh>
+#include <mln/fun/p2b/big_chess.hh>
+#include <tests/data.hh>
+#include <doc/tutorial/tools/sample_utils.hh>
+
+namespace mln
+{
+
+ struct saturate_rgb8 : public Function_v2v<saturate_rgb8>
+ {
+
+ typedef value::rgb8 result;
+
+ value::rgb8 operator()(const value::rgb8& v) const
+ {
+ value::rgb8 v2 = v;
+ v2.red() > 50 ? v2.red() -= 50 : v2.red() = 0;
+ v2.green() > 50 ? v2.green() -= 50 : v2.green() = 0;
+ v2.blue() > 50 ? v2.blue() -= 50 : v2.blue() = 0;
+ return v2;
+ }
+
+ };
+
+} // end of namespace mln
+
+// \{
+namespace mln
+{
+
+ struct my_ext : public Function_p2v<my_ext>
+ {
+
+ typedef value::rgb8 result;
+
+ value::rgb8 operator()(const point2d& p) const
+ {
+ if ((p.row() + p.col()) % 20)
+ return literal::black;
+ return literal::white;
+ }
+
+ };
+
+} // end of namespace mln
+// \}
+
+int main()
+{
+ using namespace mln;
+ using value::rgb8;
+
+ border::thickness = 5;
+
+ // \{
+ image2d<rgb8> lena;
+ io::ppm::load(lena, MLN_IMG_DIR "/small.ppm");
+ box2d bbox_enlarged = lena.domain();
+ bbox_enlarged.enlarge(border::thickness);
+ mln_VAR(ima_roi, lena | fun::p2b::big_chess<box2d>(lena.domain(), 10));
+ // \}
+
+ image2d<rgb8> tmp;
+ initialize(tmp, lena);
+ data::fill(tmp, literal::black);
+ data::paste(ima_roi, tmp);
+ doc::ppmsave(tmp, "extend");
+
+ // \{
+ mln_VAR(ext_with_val, extended_to(extend(ima_roi, literal::blue), bbox_enlarged));
+ // \}
+ doc::ppmsave(ext_with_val, "extend");
+
+ // \{
+ mln_VAR(ext_with_fun, extended_to(extend(ima_roi, my_ext()), bbox_enlarged));
+ // \}
+ doc::ppmsave(ext_with_fun, "extend");
+
+
+ // \{
+ mln_VAR(ext_with_ima, extend(ima_roi, lena));
+ // \}
+ doc::ppmsave(ext_with_ima, "extend");
+
+ image2d<bool> mask;
+ initialize(mask, lena);
+ data::fill(mask, true);
+ data::fill((mask | ima_roi.domain()).rw(), false);
+ mln_VAR(ima_ext, level::transform(lena | (pw::value(mask) != false), saturate_rgb8()));
+ data::paste(ima_ext, lena);
+ data::paste(ima_roi, lena);
+ doc::ppmsave(lena, "extend");
+
+}
diff --git a/milena/doc/tutorial/samples/ima2d-rot.cc b/milena/doc/tutorial/samples/ima2d-rot.cc
index 6463a5c..05e12ad 100644
--- a/milena/doc/tutorial/samples/ima2d-rot.cc
+++ b/milena/doc/tutorial/samples/ima2d-rot.cc
@@ -41,7 +41,7 @@ int main()
}
draw::box(ima2, ima2.bbox(), literal::red);
- doc::ppmsave(ima2 | extended_domain, IMA2_PPM);
+ doc::ppmsave(extended_to(ima2, extended_domain), IMA2_PPM);
// \}
}
diff --git a/milena/doc/tutorial/tools/todoxygen.sh b/milena/doc/tutorial/tools/todoxygen.sh
index 0d2aae5..fa5d188 100755
--- a/milena/doc/tutorial/tools/todoxygen.sh
+++ b/milena/doc/tutorial/tools/todoxygen.sh
@@ -30,7 +30,7 @@ sed -i -e 's/≡/\&equiv/g' $out
#Doxygen wants us to preserve '\n' after commands.
#\ref and \see do not need that extra new line.
-for keyword in include section page subpage subsection image; do
+for keyword in include section page subpage subsection subsubsection image; do
sed -i -e "s/\\\\endhtmlonly\\\\$keyword/\\\\endhtmlonly\n\n\\\\$keyword/g" $out
sed -i -e "s/\\\\$keyword \(.*\)\\\\htmlonly/\\\\$keyword \1\n\n\\\\htmlonly\n/g" $out
done
diff --git a/milena/doc/tutorial/tutorial.tex b/milena/doc/tutorial/tutorial.tex
index 267d0e2..7a4de1b 100644
--- a/milena/doc/tutorial/tutorial.tex
+++ b/milena/doc/tutorial/tutorial.tex
@@ -73,6 +73,13 @@
\backslash htmlonly %
}
+\newcommand{\doxysubsubsection}[2]{%
+\label{#1}
+\backslash endhtmlonly%
+\backslash subsubsection #1 #2%
+\backslash htmlonly %
+}
+
% #1 - part number (Optional)
% #2 - file name
\newcommand{\doxycode}[2][1]{
@@ -150,6 +157,7 @@ $$
\renewcommand{\doxychapter}[2]{\chapter{#2}\label{#1}}
\renewcommand{\doxysection}[2]{\section{#2}\label{#1}}
\renewcommand{\doxysubsection}[2]{\subsection{#2}\label{#1}}
+\renewcommand{\doxysubsubsection}[2]{\subsubsection{#2}\label{#1}}
\renewcommand{\doxycode}[2][1]{\lstinputlisting[frame=single]{samples/#2-#1.cc}}
\renewcommand{\doxyrawcode}[1]{\lstinputlisting[frame=single]{samples/#1.cc.raw}}
\renewcommand{\doxyoutput}[1]{\lstinputlisting[frame=single]{outputs/#1.txt}}
@@ -564,7 +572,8 @@ restricted to the region of interest \var{roi}'. Actually this is not directly
Note the use of \code{rw()} which is mandatory due to C++ limitations. In C++,
the image created by \code{lena | roi} is \code{const}, e.g. read-only, though
-\code{data::fill} expect a \code{non-const} image, e.g. read-write.
+\code{data::fill} expect a \code{non-const} image, e.g. read-write. \code{rw()}
+is a workaround to make it read-write.
\begin{center}
\begin{tabular}{c c c}
@@ -1214,6 +1223,8 @@ image domain. In the library, both the concept of border and of extension can be
These concepts are useful in many algorithms and can avoid costly tests while
working with sites located on image edges.
+\doxysubsection{imabordersection}{Image border}
+
A border is a finite extension provided to a basic image type, such as
\type{image2d}. By default, every image is created with a border. The default width is
defined through the global variable \var{border::thickness} defined in
@@ -1234,8 +1245,6 @@ ignored while saving or printing an image.
Some operations can be performed on the border. The functions are located in
\hpath{mln/border}.\\
-FIXME: More details about border manipulation! border:get(), \ldots
-
%
\bigskip
%
@@ -1254,7 +1263,9 @@ resize & Set image border to a specific size.\\
\end{tabular} \\
-On morphed images, decribed in section \doxyref{imamorphed}, the border concept
+\doxysubsection{imextgeneral}{Generality on image extension}
+
+On morphed images, described in section \doxyref{imamorphed}, the border concept
does not exist and is generalized to the extension concept.
A simple example of a morphed image is a sub-image. A sub image does not have
border nor extension by default.
@@ -1264,8 +1275,6 @@ Another point is that an image can be used as extension. For instance, in the
case of a sub-image, you may be interested in extending the sub-image with the
image itself.
-[FIXME: schema - voir cahier]
-
The extension supports the following operations. These functions are located in
\hpath{mln/extension}.\\
@@ -1275,9 +1284,65 @@ The extension supports the following operations. These functions are located in
\begin{tabular}{l|p{10cm}}
Routine & Description \\
\hline
+adjust & Adjust the extension given a structural element.\\
+adjust\_duplicate & Adjust the size of the extension given a structural element and duplicate the image inner boundary.\\
+adjust\_fill & Adjust the size of the extension given a structural element and fill it with a value.\\
+duplicate & Duplicate the values of the image inner boundary in the extension.\\
fill & Fill the extension with a given value.\\
\end{tabular} \\
+
+In order to extend an image, a routine \code{extend} is available in
+\hpath{mln/core/routine/extend.hh}. The routine \code{extended\_to} may
+also help during debug. It allows to extend the image domain to a larger
+one. The values associated to the new sites comes from the extension.
+
+\doxysubsection{extexample}{Different extensions}
+
+Let's say we have want to extract a sub domain from an image. In the following
+example, \var{ima\_roi} holds several small rectangles from the original image.
+\doxycode[2]{extend}
+
+\begin{center}
+ \begin{tabular}{c c c}
+ \doxyimg{small-enlarged} & ~\huge{\rightarrow}~ & \doxyfigure[1]{extend}{3cm} \\
+ \var{lena} & & \var{ima\_roi} (black color means the sites are not included in the domain) \\
+ \end{tabular}
+\end{center}
+
+
+Then, we may extend this sub image with one of the three following extension type.
+
+\doxysubsubsection{extval}{Extension with a value}
+
+Let's extend with the value \code{literal::blue}.
+\doxycode[3]{extend}
+\doxyfigure[2]{extend}{3cm}
+
+Note the use of the \code{extended\_to()} routine. We used a larger bbox to
+extend the image domain. That is the reason why the image is surrounded by the
+extension value, blue.
+
+\doxysubsubsection{extfun}{Extension with a function}
+
+Let's use the following function:
+\doxycode[1]{extend}
+\doxycode[4]{extend}
+\doxyfigure[3]{extend}{3cm}
+
+\doxysubsubsection{extima}{Extension with an image}
+
+Let's extend with the original image, \var{lena}.
+\doxycode[5]{extend}
+
+\begin{center}
+ \begin{tabular}{c c}
+ \doxyfigure[4]{extend}{3cm} & \doxyfigure[5]{extend}{3cm} \\
+ \var{ext\_with\_ima}, the extended image. & The actual data in the domain (light) with its extension (dark) \\
+ \end{tabular}
+\end{center}
+
+
%----------------
\subsection*{IMPORTANT NOTE}
Many times, you may want to check if a site is part of the image before applying
@@ -1559,7 +1624,8 @@ cuboid3d & Cuboid & - \\
These predefined windows can be passed directly to a function. The headers are
located in \header{mln/core/alias/window*.hh}.
-
+\doxysubsection{wwindow}{Weighted window}
+FIXME
\doxysubsection{neighborhood}{Neighborhood}
--
1.5.6.5
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-02-23 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add DICOM support.
* mln/io/dicom/load.hh: DICOM support through GDCM library.
---
load.hh | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 388 insertions(+)
Index: trunk/milena/mln/io/dicom/load.hh
===================================================================
--- trunk/milena/mln/io/dicom/load.hh (revision 0)
+++ trunk/milena/mln/io/dicom/load.hh (revision 3418)
@@ -0,0 +1,388 @@
+// Copyright (C) 2009 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.
+
+/*
+ *
+ * Copyright (C) 1994-2005, OFFIS
+ *
+ * This software and supporting documentation were developed by
+ *
+ * Kuratorium OFFIS e.V.
+ * Healthcare Information and Communication Systems
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY
+ * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
+ * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
+ * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
+ * PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
+ *
+ * Module: dcmdata
+ *
+ * Author: Gerd Ehlers
+ *
+ * Purpose: List the contents of a dicom file
+ *
+ * Last Update: $Author: meichel $
+ * Update Date: $Date: 2005/12/08 15:40:46 $
+ * CVS/RCS Revision: $Revision: 1.55 $
+ * Status: $State: Exp $
+ *
+ * CVS/RCS Log at end of file
+ *
+ */
+
+#ifndef MLN_IO_DICOM_LOAD_HH
+# define MLN_IO_DICOM_LOAD_HH
+
+/*!
+ * \file mln/io/dicom/load.hh
+ *
+ * \brief Define a function which loads an image of kind dicom with
+ * given path.
+ *
+ */
+
+# include <mln/io/pnm/load.hh>
+
+# include <dcmtk/config/osconfig.h> /* make sure OS specific configuration is included first */
+# include <dcmtk/ofstd/ofstream.h>
+# include <dcmtk/dcmdata/dctk.h>
+# include <dcmtk/dcmdata/dcdebug.h>
+# include <dcmtk/dcmdata/cmdlnarg.h>
+# include <dcmtk/ofstd/ofconapp.h>
+# include <dcmtk/dcmdata/dcuid.h> /* for dcmtk version name */
+# include <dcmtk/dcmdata/dcistrmz.h> /* for dcmZlibExpectRFC1950Encoding */
+
+# define INCLUDE_CSTDLIB
+# define INCLUDE_CSTRING
+# include <dcmtk/ofstd/ofstdinc.h>
+
+# ifdef WITH_ZLIB
+# include <zlib.h> /* for zlibVersion() */
+# endif
+
+# define SHORTCOL 3
+# define LONGCOL 20
+# define PATH_SEPARATOR '/'
+
+
+
+namespace mln
+{
+
+ namespace io
+ {
+
+ namespace dicom
+ {
+
+ /*! Load a dicom image in a Milena image.
+ *
+ * \param[out] ima A reference to the image which will receive
+ * data.
+ * \param[in] filename The source.
+ */
+ template <typename I>
+ void load(Image<I>& ima,
+ const std::string& filename);
+
+ /*! Load a dicom image in a Milena image. To use this routine, you
+ * should specialize the template whith the value type of the
+ * image loaded. (ex : load<value::int_u8>("...") )
+ *
+ * \param[in] filename The image source.
+ *
+ * \return An image2d which contains loaded data.
+ */
+ template <typename V>
+ image2d<V> load(const std::string& filename);
+
+ /*! Load a dicom image in a Milena image. To use this routine, you
+ * should specialize the template whith the value type of the
+ * image loaded. (ex : load<value::int_u8>("...") )
+ *
+ * \param[in] filename The image source.
+ *
+ * \return An image2d which contains loaded data.
+ */
+ template <typename V>
+ image3d<V> load(const std::string& filename);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ inline
+ image2d<V> load(const std::string& filename)
+ {
+ trace::entering("mln::io::dicom::load");
+ image2d<V> ima;// = io::pnm::load<V>(DICOM, filename);
+ trace::exiting("mln::io::dicom::load");
+ return ima;
+ }
+
+ template <typename V>
+ inline
+ image3d<V> load(const std::string& filename)
+ {
+ trace::entering("mln::io::dicom::load");
+ image2d<V> ima;// = io::pnm::load<V>(DICOM, filename);
+ trace::exiting("mln::io::dicom::load");
+ return ima;
+ }
+
+
+
+
+
+
+ static OFBool printAllInstances = OFTrue;
+ static OFBool prependSequenceHierarchy = OFFalse;
+ static int printTagCount = 0;
+ static const int MAX_PRINT_TAG_NAMES = 1024;
+ static const char* printTagNames[MAX_PRINT_TAG_NAMES];
+ static const DcmTagKey* printTagKeys[MAX_PRINT_TAG_NAMES];
+ static OFCmdUnsignedInt maxReadLength = 4096; // default is 4 KB
+
+ static OFBool addPrintTagName(const char* tagName)
+ {
+ if (printTagCount >= MAX_PRINT_TAG_NAMES) {
+ std::cerr << "error: too many print Tag options (max: " << MAX_PRINT_TAG_NAMES << ")" << endl;
+ return OFFalse;
+ }
+
+ unsigned int group = 0xffff;
+ unsigned int elem = 0xffff;
+ if (sscanf(tagName, "%x,%x", &group, &elem) != 2)
+ {
+ /* it is a name */
+ const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock();
+ const DcmDictEntry *dicent = globalDataDict.findEntry(tagName);
+ if (dicent == NULL)
+ {
+ std::cerr << "error: unrecognised tag name: '" << tagName << "'" << endl;
+ dcmDataDict.unlock();
+ return OFFalse;
+ }
+ else
+ {
+ /* note for later */
+ printTagKeys[printTagCount] = new DcmTagKey(dicent->getKey());
+ }
+ dcmDataDict.unlock();
+ }
+ else
+ {
+ /* tag name has format xxxx,xxxx */
+ /* do not lookup in dictionary, tag could be private */
+ printTagKeys[printTagCount] = NULL;
+ }
+
+ printTagNames[printTagCount] = strcpy(OFstatic_cast(char*, malloc(strlen(tagName)+1)), tagName);
+ printTagCount++;
+ return OFTrue;
+ }
+
+
+ template <typename I>
+ static void printResult(Image<I>& ima, DcmStack& stack, size_t printFlags)
+ {
+ unsigned long n = stack.card();
+ if (n == 0)
+ return;
+
+ if (prependSequenceHierarchy) {
+ /* print the path leading up to the top stack elem */
+ for (unsigned long i = n - 1; i >= 1; i--) {
+ DcmObject *dobj = stack.elem(i);
+ /* do not print if a DCM_Item as this is not
+ * very helpful to distinguish instances.
+ */
+ if (dobj != NULL && dobj->getTag().getXTag() != DCM_Item) {
+ char buf[512];
+ sprintf(buf, "(%x,%x).",
+ OFstatic_cast(unsigned, dobj->getGTag()),
+ OFstatic_cast(unsigned, dobj->getETag()));
+ std::cout << buf;
+ }
+ }
+ }
+
+ /* print the tag and its value */
+ DcmObject *dobj = stack.top();
+ dobj->print(std::cout, printFlags);
+ }
+
+ template <typename I>
+ static int dumpFile(Image<I>& ima,
+ const char *ifname,
+ const E_FileReadMode readMode,
+ const E_TransferSyntax xfer,
+ const size_t printFlags,
+ const OFBool loadIntoMemory,
+ const OFBool stopOnErrors,
+ const OFBool writePixelData,
+ const char *pixelDirectory)
+ {
+ int result = 0;
+
+ DcmFileFormat dfile;
+ DcmObject *dset = &dfile;
+
+ if (readMode == ERM_dataset)
+ dset = dfile.getDataset();
+
+ // Load file
+
+ OFCondition cond = dfile.loadFile(ifname, xfer, EGL_noChange, maxReadLength, readMode);
+
+ // Read error
+
+ if (!cond.good())
+ {
+ std::cerr << "error: " << dfile.error().text()
+ << ": reading file: "<< ifname << endl;
+ result = 1;
+ if (stopOnErrors)
+ return result;
+ }
+
+ if (loadIntoMemory)
+ dfile.loadAllDataIntoMemory();
+
+ if (printTagCount == 0)
+ {
+ if (writePixelData)
+ {
+ OFString str = ifname;
+ OFString rname = pixelDirectory;
+ if ((rname.length() > 0) && (rname[rname.length() - 1] != PATH_SEPARATOR))
+ rname += PATH_SEPARATOR;
+ size_t pos = str.find_last_of(PATH_SEPARATOR);
+ if (pos == OFString_npos)
+ rname += str;
+ else
+ rname += str.substr(pos + 1);
+ size_t counter = 0;
+ dset->print(std::cout, printFlags, 0 /*level*/, rname.c_str(), &counter);
+ }
+ else
+ dset->print(std::cout, printFlags);
+ }
+ else
+ {
+ /* only print specified tags */
+ for (int i = 0; i < printTagCount; i++)
+ {
+ unsigned int group = 0xffff;
+ unsigned int elem = 0xffff;
+ DcmTagKey searchKey;
+ const char* tagName = printTagNames[i];
+ if (printTagKeys[i])
+ searchKey = *printTagKeys[i];
+ else
+ {
+ if (sscanf(tagName, "%x,%x", &group, &elem) == 2)
+ searchKey.set(group, elem);
+ else
+ {
+ std::cerr << "Internal ERROR in File " << __FILE__ << ", Line "
+ << __LINE__ << std::endl
+ << "-- Named tag inconsistency" << std::endl;
+ abort();
+ }
+ }
+
+ DcmStack stack;
+ if (dset->search(searchKey, stack, ESM_fromHere, OFTrue) == EC_Normal)
+ {
+ printResult(ima, stack, printFlags);
+ if (printAllInstances)
+ {
+ while (dset->search(searchKey, stack, ESM_afterStackTop, OFTrue) == EC_Normal)
+ printResult(ima, stack, printFlags);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ template <typename I>
+ inline
+ void load(Image<I>& ima,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::dicom::load");
+
+ std::ifstream file(filename.c_str());
+ if (! file)
+ {
+ std::cerr << "error: cannot open file '" << filename << "'!";
+ abort();
+ }
+
+ int opt_debugMode = 0;
+ OFBool loadIntoMemory = OFTrue;
+ size_t printFlags = DCMTypes::PF_shortenLongTagValues /*| DCMTypes::PF_showTreeStructure*/;
+ OFBool printFilename = OFFalse;
+ OFBool writePixelData = OFFalse;
+ E_FileReadMode readMode = ERM_autoDetect;
+ E_TransferSyntax xfer = EXS_Unknown;
+ OFBool stopOnErrors = OFTrue;
+ const char *current = NULL;
+ const char *pixelDirectory = NULL;
+
+
+ /* make sure data dictionary is loaded */
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ std::cerr << "Warning: no data dictionary loaded, "
+ << "check environment variable: "
+ << DCM_DICT_ENVIRONMENT_VARIABLE;
+ }
+
+ int errorCount = 0;
+ dumpFile(ima, current, readMode, xfer, printFlags, loadIntoMemory, stopOnErrors,
+ writePixelData, pixelDirectory);
+
+ trace::exiting("mln::io::dicom::load");
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::io::dicom
+
+ } // end of namespace mln::io
+
+} // end of namespace mln
+
+
+#endif // ! MLN_IO_DICOM_LOAD_HH
1
0
* mln/labeling/mean_values.hh: add a more generic version.
* tests/labeling/Makefile.am,
* tests/labeling/mean_values.cc: add missing test.
---
milena/ChangeLog | 9 ++++
milena/mln/labeling/mean_values.hh | 52 ++++++++++++++++++-------
milena/tests/labeling/Makefile.am | 2 +
milena/tests/labeling/mean_values.cc | 70 ++++++++++++++++++++++++++++++++++
4 files changed, 119 insertions(+), 14 deletions(-)
create mode 100644 milena/tests/labeling/mean_values.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 53827ae..62d0de4 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,14 @@
2009-02-23 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Add a missing test for labeling::mean_values.
+
+ * mln/labeling/mean_values.hh: add a more generic version.
+
+ * tests/labeling/Makefile.am,
+ * tests/labeling/mean_values.cc: add missing test.
+
+2009-02-23 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Various small fixes.
* doc/tutorial/samples/win-create-1.cc: fix ref output.
diff --git a/milena/mln/labeling/mean_values.hh b/milena/mln/labeling/mean_values.hh
index 7014c59..0565abb 100644
--- a/milena/mln/labeling/mean_values.hh
+++ b/milena/mln/labeling/mean_values.hh
@@ -28,6 +28,15 @@
#ifndef MLN_LABELING_MEAN_VALUES_HH
# define MLN_LABELING_MEAN_VALUES_HH
+/// \file mln/labeling/mean_values.hh
+///
+/// Construct from a labeled image a new image, the labels values are
+/// replaced by the components mean values.
+///
+/// \todo handle mean value for label 0 correctly.
+/// \todo merge rgb and generic version.
+
+
# include <mln/core/concept/image.hh>
# include <mln/core/alias/vec3d.hh>
@@ -39,11 +48,6 @@
# include <mln/literal/colors.hh>
-/// \file mln/labeling/mean_values.hh
-///
-/// Construct from a labeled image a new image, the labels values are
-/// replaced by the components mean values.
-
namespace mln
{
@@ -92,15 +96,35 @@ namespace mln
template <typename I, typename L>
mln_concrete(I)
- mean_values(const Image<I>& input,
- const Image<L>& lbl, mln_value(L) nlabels)
+ mean_values(const Image<I>& input_,
+ const Image<L>& lbl_, mln_value(L) nlabels)
{
- internal::mean_values_tests(input, lbl, nlabels);
+ trace::entering("mln::labeling::impl::generic::mean_values");
+
+ internal::mean_values_tests(input_, lbl_, nlabels);
+
+ const I& input = exact(input_);
+ const L& lbl = exact(lbl_);
+ typedef mln_value(L) LV;
+ typedef mln_value(I) IV;
+
+ util::array<float> m_3f
+ = labeling::compute(accu::mean<IV>(),
+ input, // input color image
+ lbl, // watershed labeling
+ nlabels);
+ m_3f[0] = 0.f;
+
+ util::array<IV> m;
+ convert::from_to(m_3f, m);
+ m[0] = 150u; //FIXME: handle label 0 correctly.
+
+ mln_concrete(I) output = level::transform(lbl,
+ convert::to< fun::i2v::array<IV> >(m));
+
- trace::warning("labeling::impl::generic::mean_values() is not \
- implemented!");
- //FIXME: to write!
- abort();
+ trace::exiting("mln::labeling::impl::generic::mean_values");
+ return output;
}
}
@@ -110,7 +134,7 @@ namespace mln
mean_values_rgb(const Image<I>& input_,
const Image<L>& lbl_, mln_value(L) nlabels)
{
- trace::entering("mln::labeling::mean_values_rgb");
+ trace::entering("mln::labeling::impl::mean_values_rgb");
internal::mean_values_tests(input_, lbl_, nlabels);
@@ -131,7 +155,7 @@ namespace mln
convert::to< fun::i2v::array<mln_value(I)> >(m));
- trace::exiting("mln::labeling::mean_values_rgb");
+ trace::exiting("mln::labeling::impl::mean_values_rgb");
return output;
}
diff --git a/milena/tests/labeling/Makefile.am b/milena/tests/labeling/Makefile.am
index 083244a..6b3231f 100644
--- a/milena/tests/labeling/Makefile.am
+++ b/milena/tests/labeling/Makefile.am
@@ -10,6 +10,7 @@ check_PROGRAMS = \
flat_zones \
foreground \
level \
+ mean_values \
n_max \
regional_maxima \
regional_minima \
@@ -22,6 +23,7 @@ fill_holes_SOURCES = fill_holes.cc
flat_zones_SOURCES = flat_zones.cc
foreground_SOURCES = foreground.cc
level_SOURCES = level.cc
+mean_values_SOURCES = mean_values.cc
n_max_SOURCES = n_max.cc
regional_maxima_SOURCES = regional_maxima.cc
regional_minima_SOURCES = regional_minima.cc
diff --git a/milena/tests/labeling/mean_values.cc b/milena/tests/labeling/mean_values.cc
new file mode 100644
index 0000000..c46193a
--- /dev/null
+++ b/milena/tests/labeling/mean_values.cc
@@ -0,0 +1,70 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// 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 tests/labeling/blobs.cc
+///
+/// Test on mln::labeling::mean_values.
+
+#include <mln/core/image/image2d.hh>
+
+#include <mln/level/compare.hh>
+
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_8.hh>
+
+#include "tests/data.hh"
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::label_8;
+
+ int_u8 input_[16] = { 1, 2, 0, 1,
+ 3, 0, 2, 3,
+ 0, 0, 2, 3,
+ 1, 1, 0, 1 };
+ image2d<int_u8> input = make::image2d(input_);
+
+ label_8 lbl_[16] = { 1, 1, 0, 2,
+ 1, 0, 2, 2,
+ 0, 0, 2, 2,
+ 3, 3, 0, 2 };
+ image2d<label_8> lbl = make::image2d(lbl_);
+
+ int_u8 means_[16] = { 2, 2, 150, 2,
+ 2, 150, 2, 2,
+ 150, 150, 2, 2,
+ 1, 1, 150, 2 };
+ image2d<int_u8> means = make::image2d(means_);
+
+ image2d<int_u8> res = labeling::mean_values(input, lbl, 3);
+
+ mln_assertion(res == means);
+}
--
1.5.6.5
1
0
* doc/tutorial/samples/win-create-1.cc: fix ref output.
* doc/tutorial/tutorial.tex: change chapter alias.
* mln/core/image/extension_val.hh: fix wrong prototype of
extended_with routine.
* mln/morpho/elementary/laplacian.hh,
* mln/debug/println_with_border.spe.hh: update comments.
* mln/io/dump/load.hh: add missing assertion.
* mln/registration/all.hh: remove not existing included header.
* mln/registration/icp.hh: add missing to_vec.
* mln/transform/internal/closest_point_functor.hh: add missing
includes.
---
milena/ChangeLog | 23 ++++++++++++++++++++
milena/doc/tutorial/samples/win-create-1.cc | 4 +-
milena/doc/tutorial/tutorial.tex | 4 +-
milena/mln/core/image/extension_val.hh | 9 +++----
milena/mln/debug/println_with_border.spe.hh | 10 ++++----
milena/mln/io/dump/load.hh | 1 +
milena/mln/morpho/elementary/laplacian.hh | 11 ++++-----
milena/mln/registration/all.hh | 1 -
milena/mln/registration/icp.hh | 2 +-
.../transform/internal/closest_point_functor.hh | 2 +
10 files changed, 45 insertions(+), 22 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 58919f4..53827ae 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,28 @@
2009-02-23 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Various small fixes.
+
+ * doc/tutorial/samples/win-create-1.cc: fix ref output.
+
+ * doc/tutorial/tutorial.tex: change chapter alias.
+
+ * mln/core/image/extension_val.hh: fix wrong prototype of
+ extended_with routine.
+
+ * mln/morpho/elementary/laplacian.hh,
+ * mln/debug/println_with_border.spe.hh: update comments.
+
+ * mln/io/dump/load.hh: add missing assertion.
+
+ * mln/registration/all.hh: remove not existing included header.
+
+ * mln/registration/icp.hh: add missing to_vec.
+
+ * mln/transform/internal/closest_point_functor.hh: add missing
+ includes.
+
+2009-02-23 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Do not use mln_VAR in tests.
* tests/core/routine/extend.cc,
diff --git a/milena/doc/tutorial/samples/win-create-1.cc b/milena/doc/tutorial/samples/win-create-1.cc
index 92c962c..b6d6e89 100644
--- a/milena/doc/tutorial/samples/win-create-1.cc
+++ b/milena/doc/tutorial/samples/win-create-1.cc
@@ -5,9 +5,9 @@ int main()
// \{
window2d win;
- win.insert(-1, 0);
- win.insert( 0, -1);
win.insert(-1, -1);
+ win.insert(-1, 0);
+ win.insert(-1, 1);
// \}
}
diff --git a/milena/doc/tutorial/tutorial.tex b/milena/doc/tutorial/tutorial.tex
index f610437..267d0e2 100644
--- a/milena/doc/tutorial/tutorial.tex
+++ b/milena/doc/tutorial/tutorial.tex
@@ -326,7 +326,7 @@ $$
- \backslash subpage imamemmgmt
- \backslash subpage basicops
- \backslash subpage graphandima
-- \backslash subpage functions
+- \backslash subpage funs
- \backslash subpage arithmops
- \backslash subpage mathtools
- \backslash subpage debugtools
@@ -2377,7 +2377,7 @@ Output:
%====================================
\newpage
\clearpage
-\doxychapter{functions}{Functions}
+\doxychapter{funs}{Functions}
FIXME write it
diff --git a/milena/mln/core/image/extension_val.hh b/milena/mln/core/image/extension_val.hh
index 45f1926..9dbfadc 100644
--- a/milena/mln/core/image/extension_val.hh
+++ b/milena/mln/core/image/extension_val.hh
@@ -268,15 +268,14 @@ namespace mln
target = static_cast<V>(model.extension());
}
- template <typename I, typename J>
- extension_ima<I,J>
- extended_with(Image<I>& ima, const Image<J> ext)
+ template <typename I>
+ extension_val<I>
+ extended_with(Image<I>& ima, const mln_value(I)& val)
{
mlc_not_equal(mln_trait_image_ext_domain(I),
trait::image::ext_domain::none)::check();
mln_precondition(exact(ima).is_valid());
- mln_precondition(exact(ext).is_valid());
- extension_ima<I,J> tmp(exact(ima), exact(ext));
+ extension_val<I> tmp(exact(ima), val);
return tmp;
}
diff --git a/milena/mln/debug/println_with_border.spe.hh b/milena/mln/debug/println_with_border.spe.hh
index 825deb3..4c822d3 100644
--- a/milena/mln/debug/println_with_border.spe.hh
+++ b/milena/mln/debug/println_with_border.spe.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,10 +29,9 @@
#ifndef MLN_DEBUG_PRINTLN_WITH_BORDER_SPE_HH
# define MLN_DEBUG_PRINTLN_WITH_BORDER_SPE_HH
-/*! \file mln/debug/println_with_border_spe.hh
- *
- * \brief Specializations for mln::debug::println_with_border.
- */
+/// \file mln/debug/println_with_border_spe.hh
+///
+/// Specializations for mln::debug::println_with_border.
# ifndef MLN_DEBUG_PRINTLN_WITH_BORDER_HH
# error "Forbidden inclusion of *.spe.hh"
diff --git a/milena/mln/io/dump/load.hh b/milena/mln/io/dump/load.hh
index 21d6534..bc6a051 100644
--- a/milena/mln/io/dump/load.hh
+++ b/milena/mln/io/dump/load.hh
@@ -89,6 +89,7 @@ namespace mln
mln_concrete(I) result(box<P>(pmin, pmax));
initialize(ima, result);
+ mln_assertion(exact(ima).is_valid());
}
diff --git a/milena/mln/morpho/elementary/laplacian.hh b/milena/mln/morpho/elementary/laplacian.hh
index 974504c..0b2ad4e 100644
--- a/milena/mln/morpho/elementary/laplacian.hh
+++ b/milena/mln/morpho/elementary/laplacian.hh
@@ -29,12 +29,11 @@
#ifndef MLN_MORPHO_ELEMENTARY_LAPLACIAN_HH
# define MLN_MORPHO_ELEMENTARY_LAPLACIAN_HH
-/*! \file mln/morpho/elementary/laplacian.hh
- *
- * \brief Morphological elementary laplacian.
- *
- * \todo Handle the set case?
- */
+/// \file mln/morpho/elementary/laplacian.hh
+///
+/// Morphological elementary laplacian.
+///
+/// \todo Handle the set case?
# include <mln/morpho/elementary/gradient_internal.hh>
# include <mln/morpho/elementary/gradient_external.hh>
diff --git a/milena/mln/registration/all.hh b/milena/mln/registration/all.hh
index bb4e18e..5d4c5f7 100644
--- a/milena/mln/registration/all.hh
+++ b/milena/mln/registration/all.hh
@@ -46,7 +46,6 @@ namespace mln
# include <mln/registration/get_rot.hh>
# include <mln/registration/get_rtransf.hh>
# include <mln/registration/icp.hh>
-# include <mln/registration/multiscale.hh>
# include <mln/registration/registration.hh>
#endif // ! MLN_REGISTRATION_ALL_HH
diff --git a/milena/mln/registration/icp.hh b/milena/mln/registration/icp.hh
index d484f5c..a5ad215 100644
--- a/milena/mln/registration/icp.hh
+++ b/milena/mln/registration/icp.hh
@@ -650,7 +650,7 @@ namespace mln
image3d<value::rgb8> tmp_ = duplicate(debug);
mln_piter(p_array<P>) p_dbg(P_);
for_all(p_dbg)
- tmp_(qR_old.rotate(p_dbg) + qT_old) = literal::green;
+ tmp_(qR_old.rotate(p_dbg.to_vec()) + qT_old) = literal::green;
std::ostringstream ss;
ss << "tmp_0";
if (k < 10)
diff --git a/milena/mln/transform/internal/closest_point_functor.hh b/milena/mln/transform/internal/closest_point_functor.hh
index 098c994..5cbac15 100644
--- a/milena/mln/transform/internal/closest_point_functor.hh
+++ b/milena/mln/transform/internal/closest_point_functor.hh
@@ -32,7 +32,9 @@
///
/// Closest point functor.
+# include <mln/core/site_set/p_array.hh>
# include <mln/core/macros.hh>
+# include <mln/data/fill.hh>
# include <mln/trait/ch_value.hh>
namespace mln
--
1.5.6.5
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-02-23 Frederic Bour <bour(a)lrde.epita.fr>
Work on meta-functions and overloading added..
* Makefile: .
* accu_trait.hh: Remove.
* accuprops.cc: Remove.
* accuprops2.cc: Remove.
* algebraic.cc: Remove.
* closing_area.cc: Remove.
* connected_filter.hh: Remove.
* leveling.cc: Remove.
* leveling_filter.hh: Remove.
* mean.hh: Remove.
* meantest.cc: Remove.
* old/accu_trait.hh: New.
* old/accuprops.cc: New.
* old/accuprops2.cc: New.
* old/algebraic.cc: New.
* old/closing_area.cc: New.
* old/connected_filter.hh: New.
* old/leveling.cc: New.
* old/leveling_filter.hh: New.
* old/mean.hh: New.
* old/meantest.cc: New.
* old/p2p: New.
* old/value_wrapper.hh: New.
* old: New.
* overload.cc: New.
* p2p: Remove.
* value_wrapper.hh: Remove.
---
Makefile | 2
old/accu_trait.hh | 94 ++++++++++
old/accuprops.cc | 331 +++++++++++++++++++++++++++++++++++
old/accuprops2.cc | 380 +++++++++++++++++++++++++++++++++++++++++
old/algebraic.cc | 406 ++++++++++++++++++++++++++++++++++++++++++++
old/closing_area.cc | 50 +++++
old/connected_filter.hh | 123 +++++++++++++
old/leveling.cc | 47 +++++
old/leveling_filter.hh | 381 +++++++++++++++++++++++++++++++++++++++++
old/mean.hh | 202 +++++++++++++++++++++
old/meantest.cc | 21 ++
old/p2p/Makefile | 12 +
old/p2p/compose_p2p.hh | 44 ++++
old/p2p/p2p_morpher.hh | 284 ++++++++++++++++++++++++++++++
old/p2p/symmetry_p2p.hh | 47 +++++
old/p2p/test_morph_image.cc | 62 ++++++
old/p2p/translate_p2p.hh | 43 ++++
old/value_wrapper.hh | 188 ++++++++++++++++++++
overload.cc | 283 ++++++++++++++++++++++++++++++
19 files changed, 2999 insertions(+), 1 deletion(-)
Index: trunk/milena/sandbox/fred/accuprops.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/meantest.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/accuprops2.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/connected_filter.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/leveling_filter.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/leveling.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/closing_area.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/value_wrapper.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/accu_trait.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/algebraic.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/mean.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/fred/overload.cc
===================================================================
--- trunk/milena/sandbox/fred/overload.cc (revision 0)
+++ trunk/milena/sandbox/fred/overload.cc (revision 3415)
@@ -0,0 +1,283 @@
+#include <mln/core/concept/function.hh>
+#include <mln/core/concept/value.hh>
+#include <mln/fun/internal/resolve.hh>
+#include <mln/trait/op/plus.hh>
+
+// Avantage de cette methode:
+// - la surcharge est rendue effectivement possible pour des familles de types
+// et permet de passer en argument une fonction meme s'il existe de multiple definitions
+// (^^ sic pour la qualite de l'explication ^^)
+// - de maniere souple (set_previse_binary & set_binary).
+//
+// Inconvenients:
+// - beaucoup de code/verbeux
+// - necessite de reecrire la resolution a la main
+// - l'implementation des differentes surcharge n'est pas aussi intuitive qu'en C++
+// naturel
+// - passage par les categories. Impossible de tirer parti de la hierarchie
+// "naturelle" des types en C++.
+//
+
+// INF
+namespace mln
+{
+
+ // Forward declaration.
+ namespace fun {
+ namespace vv2v {
+ template <typename T> struct inf;
+ }
+ }
+
+
+ namespace trait
+ {
+
+ // Default (whatever the category):
+ // "inf" performs a "min"!
+ template <template <class> class Category, typename T>
+ struct set_unary_< fun::vv2v::inf, Category, T >
+ {
+ typedef set_unary_< fun::vv2v::inf, Category, T > ret;
+
+ static T exec(const T& t1, const T& t2)
+ {
+ return t1 < t2 ? t1 : t2;
+ }
+
+ // In the case of a binary function with two different argument
+ // types, we shall instrument this definition with the result
+ // type...
+ };
+
+ } // mln::trait
+
+
+
+ namespace fun
+ {
+
+ namespace vv2v
+ {
+
+ // fun::vv2v::inf<T>
+
+ template <typename T>
+ struct inf : Function_vv2v< inf<T> >
+ {
+ typedef T result;
+
+ typedef mln_fun_internal_resolve(inf) impl;
+
+ T operator()(const T& t1, const T& t2) const
+ {
+ return impl::exec(t1, t2);
+ }
+ };
+
+
+ // fun::vv2v::meta::inf
+
+ namespace meta
+ {
+
+ struct inf
+ {
+
+ // A meta-fun can act as a function :-)
+
+ template <typename T>
+ T operator()(const T& t1, const T& t2) const
+ // Here, we know the result type of vv2v::inf<T> so
+ // we explictly write it.
+ {
+ fun::vv2v::inf<T> f;
+ return f(t1, t2);
+ }
+
+ // The "meta-fun -> fun" code is similar to the one in
+ // mln/accu/min.hh
+ template <typename T>
+ struct with
+ {
+ typedef fun::vv2v::inf<T> ret;
+ };
+ };
+
+ } // mln::fun::vv2v::meta
+
+ } // mln::fun::vv2v
+
+ } // mln::fun
+
+ // Yay! A special type equipped with a particular 'inf'.
+
+ struct rgb : Value<rgb>
+ {
+ typedef rgb enc;
+ typedef rgb equiv; // Those couple of typedefs are required by the concept.
+ rgb() {}
+ rgb(int r, int g, int b) : r(r), g(g), b(b) {}
+ int r, g, b;
+ };
+
+ std::ostream& operator<<(std::ostream& ostr, const rgb& c)
+ {
+ ostr << c.r << ' ' << c.g << ' ' << c.b;
+ }
+
+ namespace trait
+ {
+
+ template <>
+ struct set_precise_unary_< fun::vv2v::inf, rgb >
+ {
+ typedef set_precise_unary_< fun::vv2v::inf, rgb > ret;
+
+ static rgb exec(const rgb& c1, const rgb& c2)
+ {
+ // "Inf" is component-wise "min".
+ return rgb(c1.r < c2.r ? c1.r : c2.r,
+ c1.g < c2.g ? c1.g : c2.g,
+ c1.b < c2.b ? c1.b : c2.b);
+ }
+ };
+
+ } // mln::trait
+
+} // mln
+
+// PLUS
+namespace mln
+{
+
+ // Forward declaration.
+ namespace fun {
+ namespace vv2v {
+ template <typename L, typename R> struct plus;
+ }
+ }
+
+
+ namespace trait
+ {
+
+ // Default (whatever the category):
+ // "inf" performs a "min"!
+ template <template <class> class Category_L, typename L, template <class> class Category_R, typename R>
+ struct set_binary_< fun::vv2v::plus, Category_L, L, Category_R, R>
+ {
+ typedef set_binary_< fun::vv2v::plus, Category_L, L, Category_R, R> ret;
+
+ static mln_trait_op_plus(L,R) exec(const L& t1, const R& t2)
+ {
+ return t1 + t2;
+ }
+
+ // In the case of a binary function with two different argument
+ // types, we shall instrument this definition with the result
+ // type...
+ };
+
+ } // mln::trait
+
+
+
+ namespace fun
+ {
+
+ namespace vv2v
+ {
+
+ // fun::vv2v::plus<L,R>
+
+ template <typename L, typename R>
+ struct plus : Function_vv2v< plus<L,R> >
+ {
+ typedef mln_trait_op_plus(L,R) result;
+
+ typedef mln_fun_internal_resolve(plus) impl;
+
+ result operator()(const L& t1, const R& t2) const
+ {
+ return impl::exec(t1, t2);
+ }
+ };
+
+
+ // fun::vv2v::meta::plus
+
+ namespace meta
+ {
+
+ struct plus
+ {
+
+ // A meta-fun can act as a function :-)
+
+ template <typename L, typename R>
+ typename fun::vv2v::plus<L,R>::result operator()(const L& t1, const R& t2) const
+ // Here, we know the result type of vv2v::plus<L,R> so
+ // we explictly write it.
+ {
+ fun::vv2v::plus<L,R> f;
+ return f(t1, t2);
+ }
+
+ // The "meta-fun -> fun" code is similar to the one in
+ // mln/accu/min.hh
+ template <typename L, typename R>
+ struct with
+ {
+ typedef fun::vv2v::plus<L,R> ret;
+ };
+ };
+
+ } // mln::fun::vv2v::meta
+
+ } // mln::fun::vv2v
+
+ } // mln::fun
+
+ namespace trait
+ {
+
+ template <>
+ struct set_precise_binary_< fun::vv2v::plus, rgb, rgb >
+ {
+ typedef set_precise_binary_< fun::vv2v::plus, rgb, rgb > ret;
+
+ static rgb exec(const rgb& c1, const rgb& c2)
+ {
+ // "Inf" is component-wise "min".
+ return rgb(c1.r + c2.r,
+ c1.g + c2.g,
+ c1.b + c2.b);
+ }
+ };
+
+ template <>
+ struct set_precise_binary_< mln::trait::op::plus, rgb, rgb >
+ {
+ typedef rgb ret;
+ };
+
+ } // mln::trait
+
+} // mln
+
+using namespace mln;
+
+int main()
+{
+ fun::vv2v::meta::inf inf;
+ std::cout << inf(3, 5) << std::endl;
+
+ rgb c1(1, 2, 3), c2(2, 1, 2);
+ std::cout << inf(c1, c2) << std::endl;
+
+ fun::vv2v::meta::plus plus;
+ std::cout << plus(plus(3.1f, 5), 3.1415926535) << std::endl;
+
+ std::cout << plus(c1, c2) << std::endl;
+}
Index: trunk/milena/sandbox/fred/Makefile
===================================================================
--- trunk/milena/sandbox/fred/Makefile (revision 3414)
+++ trunk/milena/sandbox/fred/Makefile (revision 3415)
@@ -1,4 +1,4 @@
-TARGET=connected
+TARGET=overload
OBJS=$(TARGET).o
OLENADIR=../../..
Index: trunk/milena/sandbox/fred/old/p2p/compose_p2p.hh
===================================================================
--- trunk/milena/sandbox/fred/old/p2p/compose_p2p.hh (revision 0)
+++ trunk/milena/sandbox/fred/old/p2p/compose_p2p.hh (revision 3415)
@@ -0,0 +1,44 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/macros.hh>
+#include <mln/core/alias/point2d.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/core/var.hh>
+
+namespace mln
+{
+
+ template <typename P, typename F, typename G>
+ class compose_t : public Function_p2p< compose_t<P, F, G> >
+ {
+ public:
+ typedef P result;
+ typedef compose_t<P, typename G::inverse, typename F::inverse> inverse;
+
+ compose_t (const F& f, const G& g)
+ : f_ (f), g_ (g) {};
+
+ P operator() (const P& point) const
+ {
+ return (f_ (g_ (point)));
+ };
+
+ inverse inv () const
+ {
+ inverse comp(g_.inv (), f_.inv ());
+ return comp;
+ };
+
+ private:
+ const F f_;
+ const G g_;
+ };
+
+ template <typename F, typename G>
+ compose_t<typename F::result, F, G> operator* (const Function_p2p< F >& f,
+ const Function_p2p< G >& g)
+ {
+ compose_t<typename F::result, F, G> comp (exact (f), exact (g));
+ return comp;
+ }
+
+}
\ No newline at end of file
Index: trunk/milena/sandbox/fred/old/p2p/symmetry_p2p.hh
===================================================================
--- trunk/milena/sandbox/fred/old/p2p/symmetry_p2p.hh (revision 0)
+++ trunk/milena/sandbox/fred/old/p2p/symmetry_p2p.hh (revision 3415)
@@ -0,0 +1,47 @@
+#include <mln/core/contract.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/macros.hh>
+#include <mln/core/alias/point2d.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/core/var.hh>
+
+namespace mln
+{
+
+ template <typename P>
+ class symmetry_t : public Function_p2p< symmetry_t<P> >
+ {
+ public:
+ typedef P result;
+ typedef symmetry_t<P> inverse;
+
+ symmetry_t (unsigned dim)
+ : dim_ (dim)
+ {
+ mln_assertion(dim < P::dim);
+ };
+
+ P operator() (const P& point) const
+ {
+ P pt = point;
+ pt[dim_] = -pt[dim_];
+ return pt;
+ };
+
+ inverse inv () const
+ {
+ return *this;
+ };
+
+ private:
+ const unsigned dim_;
+ };
+
+ template <typename P>
+ symmetry_t<P> flip (unsigned dim)
+ {
+ symmetry_t<P> f (dim);
+ return f;
+ }
+
+}
\ No newline at end of file
Index: trunk/milena/sandbox/fred/old/p2p/test_morph_image.cc
===================================================================
--- trunk/milena/sandbox/fred/old/p2p/test_morph_image.cc (revision 0)
+++ trunk/milena/sandbox/fred/old/p2p/test_morph_image.cc (revision 3415)
@@ -0,0 +1,62 @@
+// 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 tests/core/image/t_image.cc
+ *
+ * \brief Tests on mln::t_image.
+ */
+
+#include <mln/core/image/image2d.hh>
+
+#include <mln/debug/iota.hh>
+#include <mln/debug/println.hh>
+
+#include "trans_image.hh"
+#include "translate_p2p.hh"
+#include "symmetry_p2p.hh"
+#include "compose_p2p.hh"
+
+#include <iostream>
+
+int main()
+{
+ using namespace mln;
+
+ typedef image2d<int> I;
+
+ I ima(2, 3);
+ debug::iota(ima);
+ debug::println(ima);
+ // translate(dpoint2d(2,2)) *
+ mln_VAR(tr, transform_image(ima, flip<I::site>(0) * translate(dpoint2d(2,2)) * flip<I::site>(1)));
+ debug::println(tr);
+
+ std::cout << ima.domain () << " => " << tr.domain () << std::endl;
+
+ // FIXME: Enrich this test (exercise more features and write
+ // assertions).
+}
Index: trunk/milena/sandbox/fred/old/p2p/p2p_morpher.hh
===================================================================
--- trunk/milena/sandbox/fred/old/p2p/p2p_morpher.hh (revision 0)
+++ trunk/milena/sandbox/fred/old/p2p/p2p_morpher.hh (revision 3415)
@@ -0,0 +1,284 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_IMAGE_TRANS_IMAGE_HH
+# define MLN_CORE_IMAGE_TRANS_IMAGE_HH
+
+/*! \file sandbox/fred/trans_image.hh
+ *
+ * \brief Definition of the "transformed" image class mln::trans_image.
+ */
+
+# include <mln/core/internal/image_morpher.hh>
+# include <mln/core/site_set/box.hh>
+# include <mln/value/set.hh>
+# include <mln/core/concept/function.hh>
+# include <mln/accu/bbox.hh>
+
+namespace mln
+{
+
+ // Fwd decl.
+ template <typename I, typename F> struct trans_image;
+
+ namespace internal
+ {
+
+ /// Data structure for \c mln::trans_image<I>.
+ template <typename I, typename F>
+ struct data< trans_image<I, F> >
+ {
+ /// \brief Build the data object held by a trans_image.
+ ///
+ /// \param ima The underlying image.
+ /// \param fun The underlying functor.
+ data(I& ima, const F& fun, const box<mln_psite(I)>& box);
+
+ /// Underlying image.
+ I ima_;
+ /// Underlying transformation function.
+ // FIXME: do we need to conserve original transformation or just inverse ?
+ //F fun_;
+ typename F::inverse funinv_;
+ /// The bounding box of the morphed image.
+ box<mln_psite(I)> box_;
+ };
+
+ } // end of namespace mln::internal
+
+
+ /*! \brief Transformed image class.
+ *
+ * Applies an fun::p2p functor to coordinates of image pixels.
+ *
+ * \warning This class only works on images whose domain is a box.
+ * \warning Transformation function must transform domain to a
+ * domain with same cardinality.
+ * \warning You need to give the INVERSE of the desired transformation.
+ */
+ template <typename I, typename F>
+ class trans_image
+ : public internal::image_morpher<I, mln_value(I), mln_pset(I), trans_image<I, F> >
+ {
+ public:
+ /// Super type.
+ typedef internal::image_morpher< I, mln_value(I), mln_pset(I),
+ trans_image<I, F> > super_;
+
+ /// Point_Site associated type.
+ typedef mln_psite(I) psite;
+
+ /// Value associated type.
+ typedef mln_value(I) value;
+
+ /// Type returned by the read-write pixel value operator.
+ typedef mln_morpher_lvalue(I) lvalue;
+
+ /// Return type of read-only access.
+ typedef mln_rvalue(I) rvalue;
+
+ /// Skeleton.
+ typedef trans_image< tag::image_<I>, F > skeleton;
+
+ public:
+ /// \brief Build a transformation of an image.
+ ///
+ /// The trans_image morpher allows to apply a p2p functor to every cell
+ /// of an image.
+ /// The functor \a fun must transform points so that transformed \a ima
+ /// image domain remains a box with same cardinality.
+ ///
+ /// \param ima The underlying image.
+ /// \param fun p2p functor to apply.
+ trans_image(I& ima, const F& fun);
+
+ /// Initialize an empty image.
+ void init_(I& ima, const F& fun);
+
+ /// Test if this image has been initialized.
+ bool is_valid() const;
+
+ /// Test if a pixel value is accessible at \p p.
+ bool has(const mln_psite(I)& p) const;
+
+ /// Give the definition domain.
+ const box<mln_psite(I)>& domain() const;
+
+ /// Read-only access of pixel value at point site \p p.
+ mln_rvalue(I) operator()(const mln_psite(I)& p) const;
+
+ /// Read-write access of pixel value at point site \p p.
+ mln_morpher_lvalue(I) operator()(const mln_psite(I)& p);
+
+
+ protected:
+ /// Transform \a p point through functor.
+ mln_psite(I) transform_(const mln_psite(I)& p) const;
+ box<mln_psite(I)> transform_(const box<mln_psite(I)>& p) const;
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ // internal::data< trans_image<I,S> >
+
+ template <typename I, typename F>
+ inline
+ data< trans_image<I, F> >::data(I& ima, const F& fun, const box<mln_psite(I)>& box)
+ : ima_ (ima),
+ // FIXME: do we need to conserve original transformation or just inverse ?
+ // fun_ (fun),
+ funinv_ (fun.inv ()),
+ box_ (box)
+ {
+ }
+
+ } // end of namespace mln::internal
+
+
+ template <typename I, typename F>
+ inline
+ trans_image<I, F>::trans_image(I& ima, const F& fun)
+ {
+ init_(ima, fun);
+ }
+
+ template <typename I, typename F>
+ inline
+ void
+ trans_image<I, F>::init_(I& ima, const F& fun)
+ {
+ typedef mln_psite(I) P;
+ mln_precondition(ima.is_valid());
+
+ /* FIXME: Add a precondition on the fact that the domain of ima is
+ a box. */
+
+ // Create transformed bounding box
+ accu::bbox<P> tbox;
+
+ tbox.take_as_init (fun (ima.domain ().pmin ()));
+ tbox.take (fun (ima.domain ().pmax ()));
+
+ this->data_ = new internal::data< trans_image<I, F> >(ima, fun, tbox);
+ }
+
+
+ template <typename I, typename F>
+ inline
+ bool trans_image<I, F>::is_valid() const
+ {
+ mln_invariant(this->delegatee_()->is_valid());
+ return true;
+ }
+
+ template <typename I, typename F>
+ inline
+ bool
+ trans_image<I, F>::has(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->is_valid());
+ return this->delegatee_()->has(transform_(p));
+ }
+
+ template <typename I, typename F>
+ inline
+ mln_psite(I)
+ trans_image<I, F>::transform_(const mln_psite(I)& p) const
+ {
+ return this->data_->funinv_(p);
+ }
+
+ template <typename I, typename F>
+ inline
+ box<mln_psite(I)>
+ trans_image<I, F>::transform_(const box<mln_psite(I)>& p) const
+ {
+ typedef mln_psite(I) P;
+
+ // Create transformed bounding box
+ accu::bbox<P> tbox;
+
+ tbox.take_as_init (this->data_->funinv_ (this->data_->ima_.domain ().pmin ()));
+ tbox.take (this->data_->funinv_ (this->data_->ima_.domain ().pmax ()));
+
+ return tbox;
+ }
+
+ template <typename I, typename F>
+ inline
+ const box<mln_psite(I)>&
+ trans_image<I, F>::domain() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->box_;
+ }
+
+ template <typename I, typename F>
+ inline
+ mln_rvalue(I)
+ trans_image<I, F>::operator()(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->has(p));
+ return (*this->delegatee_())(transform_(p));
+ }
+
+ template <typename I, typename F>
+ inline
+ mln_morpher_lvalue(I)
+ trans_image<I, F>::operator()(const mln_psite(I)& p)
+ {
+ mln_precondition(this->has(p));
+ return (*this->delegatee_())(transform_(p));
+ }
+
+ template <typename I, typename F>
+ inline
+ trans_image<I, F>
+ transform_image(Image<I>& ima, const Function_p2p<F>& fun)
+ {
+ trans_image<I, F> tmp(exact(ima), exact(fun));
+ return tmp;
+ }
+
+ template <typename I, typename F>
+ inline
+ trans_image<const I, F>
+ transform_image(const Image<I>& ima, const Function_p2p<F>& fun)
+ {
+ trans_image<const I, F> tmp(exact(ima), exact(fun));
+ return tmp;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_IMAGE_T_IMAGE_HH
Index: trunk/milena/sandbox/fred/old/p2p/translate_p2p.hh
===================================================================
--- trunk/milena/sandbox/fred/old/p2p/translate_p2p.hh (revision 0)
+++ trunk/milena/sandbox/fred/old/p2p/translate_p2p.hh (revision 3415)
@@ -0,0 +1,43 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/macros.hh>
+#include <mln/core/alias/point2d.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/core/var.hh>
+
+namespace mln
+{
+
+ template <typename P>
+ class translate_t : public Function_p2p< translate_t<P> >
+ {
+ public:
+ typedef P result;
+ typedef translate_t<P> inverse;
+
+ translate_t (mln_delta(P) dp)
+ : dp_ (dp) {};
+
+ P operator() (const P& point) const
+ {
+ P pt = point;
+ return (pt + dp_);
+ };
+
+ inverse inv () const
+ {
+ translate_t<P> tmp(-dp_);
+ return tmp;
+ };
+
+ private:
+ const mln_delta(P) dp_;
+ };
+
+ template <typename D>
+ translate_t<mln_site(D)> translate (const Gdpoint<D>& delta)
+ {
+ translate_t<mln_site(D)> f (exact (delta));
+ return f;
+ }
+
+}
\ No newline at end of file
Index: trunk/milena/sandbox/fred/old/p2p/Makefile
===================================================================
--- trunk/milena/sandbox/fred/old/p2p/Makefile (revision 0)
+++ trunk/milena/sandbox/fred/old/p2p/Makefile (revision 3415)
@@ -0,0 +1,12 @@
+SRC=test_trans_image.cc
+OBJ=${SRC:.cc=.o}
+CXXFLAGS=-I ~/lrde/olena/trunk/milena
+
+all: $(OBJ)
+ g++ $<
+
+%.o: %cc
+ g++ $(CXXFLAGS) -o$@ $<
+
+clean:
+ rm -f *~ *.o a.out
\ No newline at end of file
Index: trunk/milena/sandbox/fred/old/accuprops.cc
===================================================================
--- trunk/milena/sandbox/fred/old/accuprops.cc (revision 0)
+++ trunk/milena/sandbox/fred/old/accuprops.cc (revision 3415)
@@ -0,0 +1,331 @@
+# include <iostream>
+# include <string>
+
+# include <mln/trait/undef.hh>
+# include <mln/trait/image/props.hh>
+# include <mln/trait/value_.hh>
+
+# include <mln/metal/bexpr.hh>
+# include <mln/metal/equal.hh>
+# include <mln/metal/if.hh>
+# include <mln/metal/is_const.hh>
+
+# include <mln/core/concept/image.hh>
+# include <mln/accu/all.hh>
+# include <mln/util/pix.hh>
+# include <mln/make/pix.hh>
+
+/// Shortcut to the accumulator property about untake method disponibility
+# define mln_trait_accu_has_untake(A) typename mln::trait::accu_< A >::has_untake
+
+/// Shortcut to the accumulator property about setvalue method disponibility
+# define mln_trait_accu_has_setvalue(A) typename mln::trait::accu_< A >::has_setvalue
+
+/// Shortcut to the accumulator property about stop method disponibility
+# define mln_trait_accu_has_stop(A) typename mln::trait::accu_< A >::has_stop
+
+/// Shortcut to the accumulator property about behavior when pixel is given as take() value
+/// Used for instance in mln::canvas::morpho::leveling
+# define mln_trait_accu_when_pix(A) typename mln::trait::accu_< A >::when_pix
+
+namespace mln {
+
+ namespace trait {
+
+ namespace accu {
+
+ // Basic accumulators properties
+
+ struct has_untake
+ {
+ struct any { protected: any() {}; };
+
+ struct no : any { std::string name() const { return "has_untake::no"; } };
+
+ struct yes : any { std::string name() const { return "has_untake::yes"; } };
+ };
+
+ struct has_stop
+ {
+ struct any { protected: any() {}; };
+
+ struct no : any { std::string name() const { return "has_setvalue::no"; } };
+
+ struct yes : any { std::string name() const { return "has_stop::yes"; } };
+ };
+
+ struct has_setvalue
+ {
+ struct any { protected: any() {}; };
+
+ struct no : any { std::string name() const { return "has_setvalue::no"; } };
+
+ struct yes : any { std::string name() const { return "has_setvalue::yes"; } };
+ };
+
+ // Morphological accumulators properties
+ struct when_pix
+ {
+ struct any { protected: any() {}; };
+
+ struct use_v : any { std::string name() const { return "when_pix::use_v"; } };
+
+ struct use_p : any { std::string name() const { return "when_pix::use_p"; } };
+
+ struct use_pix : any { std::string name() const { return "when_pix::use_pix"; } };
+
+ struct not_ok : any { std::string name() const { return "when_pix::not_ok"; } };
+ };
+
+ } // end of namespace mln::trait::accu
+
+ template <typename A>
+ struct undefined_accu_
+ {
+ // general
+ typedef undef has_untake;
+ typedef undef has_stop;
+ typedef undef has_setvalue;
+
+ // morpho
+ typedef accu::when_pix::not_ok when_pix;
+ // FIXME: should default be undef ?
+ };
+
+ template <typename A>
+ struct accu_ : undefined_accu_<A>
+ {
+ };
+
+ } // end of namespace mln::trait
+
+ namespace canvas {
+
+ namespace morpho {
+
+ namespace impl {
+
+ namespace generic {
+
+ template <typename I, template <typename P> class A>
+ inline
+ void
+ leveling(const Image<I>& input,
+ Accumulator< A< util::pix<I> > >& acc)
+ {
+ const I& ima = exact(input);
+ A< util::pix<I> >& a = exact(acc);
+
+ mln_piter(I) p(ima.domain());
+
+ for_all(p)
+ a.take(mln::make::pix(ima, p));
+ }
+
+ } // end of namespace mln::canvas::morpho::impl::generic
+
+ // fast implementation (only on values from pixter)
+ template <typename I, template <typename P> class A>
+ inline
+ void
+ leveling_fastest(const Image<I>& input,
+ Accumulator< A< util::pix<I> > >& acc)
+ {
+ const I& ima = exact(input);
+ A< util::pix<I> >& a = exact(acc);
+
+ mln_pixter(const I) px(ima);
+
+ for_all(px)
+ a.take(px.val());
+ }
+
+ } // end of namespace mln::canvas::morpho::impl
+
+ namespace internal {
+
+ template <typename I, typename A>
+ inline
+ void
+ leveling_dispatch(metal::false_,
+ const Image<I>& input,
+ Accumulator<A>& acc)
+ {
+ impl::generic::leveling(input, acc);
+ }
+
+ template <typename I, typename A>
+ inline
+ void
+ leveling_dispatch(metal::true_,
+ const Image<I>& input,
+ Accumulator<A>& acc)
+ {
+ impl::leveling_fastest(input, acc);
+ }
+
+ template <typename I, typename A>
+ inline
+ void
+ leveling_dispatch(const Image<I>& input,
+ Accumulator<A>& acc)
+ {
+ enum {
+ test = mlc_equal(mln_trait_image_speed(I),
+ trait::image::speed::fastest)::value
+ &&
+ mlc_equal(mln_trait_accu_when_pix(A),
+ trait::accu::when_pix::use_v)::value
+ };
+ internal::leveling_dispatch(metal::bool_<test>(),
+ input, acc);
+ }
+
+ } // end of namespace mln::canvas::morpho::internal
+
+ // Facade.
+ template <typename I, template <typename P> class A>
+ inline
+ void
+ leveling(const Image<I>& input,
+ Accumulator< A< util::pix<I> > >& acc)
+ {
+ internal::leveling_dispatch(input, acc);
+ }
+
+ } // end of namespace mln::canvas::morpho
+
+ } // end of namespace mln::canvas
+
+ namespace morpho {
+
+ namespace accu {
+
+ namespace internal {
+
+ template <typename V>
+ struct sum_handling_pixels
+ { typedef mln_sum(V) ret; };
+
+ template <typename I>
+ struct sum_handling_pixels< util::pix<I> >
+ { typedef mln_sum(mln_value(I)) ret; };
+
+ } // end of namespace mln::morpho::accu::internal
+
+ template <typename T>
+ /// Morphological (i.e. for pixel and pixel values) accumulator calculating mean.
+ /// FIXME: is inclusion polyphormism really appliable ?
+ struct mean : public mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret>,
+ public Accumulator< mean<T> >
+ {
+ typedef mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret> super;
+ typedef typename super::result result;
+
+ using super::operator result;
+ using super::take;
+
+ void take(const mean<T>& m);
+ };
+
+ template <typename I>
+ struct mean< util::pix<I> > : public mean< mln_value(I) >,
+ public Accumulator< mean< util::pix<I> > >
+ {
+ typedef mean< mln_value(I) > super;
+ typedef util::pix<I> argument;
+ typedef typename super::result result;
+
+ using super::operator result;
+ using super::take;
+
+ void take(const argument& t);
+ void take(const mean< util::pix<I> >& m);
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename T>
+ inline
+ void mean<T>::take(const mean<T>& m)
+ {
+ this->super::take(m);
+ }
+
+ template <typename I>
+ inline
+ void mean< util::pix<I> >::take(const mean< util::pix<I> >::argument& t)
+ {
+ this->mean< mln_value(I) >::take(t.v());
+ }
+
+ template <typename I>
+ inline
+ void mean< util::pix<I> >::take(const mean< util::pix<I> >& m)
+ {
+ this->super::take(m);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho::accu
+
+ } // end of namespace mln::morpho
+
+ namespace trait {
+
+ template <typename I>
+ struct accu_< morpho::accu::mean< util::pix<I> > > :
+ public undefined_accu_ < morpho::accu::mean< util::pix<I> > >
+ {
+ typedef accu::when_pix::use_v when_pix;
+ };
+
+ } // end of namespace mln::trait
+
+} // end of namespace mln
+
+# include <mln/accu/all.hh>
+# include <mln/core/image/image2d.hh>
+
+# include <mln/debug/iota.hh>
+# include <mln/debug/println.hh>
+# include <mln/core/var.hh>
+# include <mln/util/timer.hh>
+int main()
+{
+ typedef mln::image2d<int> I;
+
+ I ima(1000, 1000);
+ mln::morpho::accu::mean< mln::util::pix<I> > acc;
+
+ float elapsed;
+ mln::util::timer chrono;
+
+ mln::debug::iota(ima);
+ std::cout << "50 mean of a 1000x1000 image2d<int>" << std::endl;
+
+ acc.init();
+ chrono.start();
+ for (int i = 0; i < 50; i++)
+ mln::canvas::morpho::leveling(ima, acc);
+ elapsed = chrono.stop();
+
+ std::cout << "(auto) " << elapsed << "s : " << acc.to_result() << std::endl;
+
+ acc.init();
+ chrono.start();
+ for (int i = 0; i < 50; i++)
+ mln::canvas::morpho::impl::generic::leveling(ima, acc);
+ elapsed = chrono.stop();
+
+ std::cout << "(generic) " << elapsed << "s : " << acc.to_result() << std::endl;
+
+ acc.init();
+ chrono.start();
+ for (int i = 0; i < 50; i++)
+ mln::canvas::morpho::impl::leveling_fastest(ima, acc);
+ elapsed = chrono.stop();
+
+ std::cout << "(fast) " << elapsed << "s : " << acc.to_result() << std::endl;
+}
Index: trunk/milena/sandbox/fred/old/meantest.cc
===================================================================
--- trunk/milena/sandbox/fred/old/meantest.cc (revision 0)
+++ trunk/milena/sandbox/fred/old/meantest.cc (revision 3415)
@@ -0,0 +1,21 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+#include "mean.hh"
+
+int main()
+{
+ typedef mln::image2d<int> I;
+ mln::morpho::attribute::mean<I> m;
+
+ m.take (2);
+ m.take (3);
+ m.take (4);
+
+ std::cout << m.to_result () << std::endl;
+
+ m.set_value (6);
+ m.take (3);
+ m.take (9);
+
+ std::cout << m.to_result () << std::endl;
+}
Index: trunk/milena/sandbox/fred/old/accuprops2.cc
===================================================================
--- trunk/milena/sandbox/fred/old/accuprops2.cc (revision 0)
+++ trunk/milena/sandbox/fred/old/accuprops2.cc (revision 3415)
@@ -0,0 +1,380 @@
+# include <iostream>
+# include <string>
+
+# include <mln/trait/undef.hh>
+# include <mln/trait/image/props.hh>
+# include <mln/trait/value_.hh>
+
+# include <mln/metal/bexpr.hh>
+# include <mln/metal/equal.hh>
+# include <mln/metal/if.hh>
+# include <mln/metal/is_const.hh>
+
+# include <mln/core/concept/image.hh>
+# include <mln/accu/all.hh>
+# include <mln/util/pix.hh>
+# include <mln/make/pix.hh>
+
+/// Shortcut to the accumulator property about untake method disponibility
+# define mln_trait_accu_has_untake(A) typename mln::trait::accu_< A >::has_untake
+
+/// Shortcut to the accumulator property about setvalue method disponibility
+# define mln_trait_accu_has_setvalue(A) typename mln::trait::accu_< A >::has_setvalue
+
+/// Shortcut to the accumulator property about stop method disponibility
+# define mln_trait_accu_has_stop(A) typename mln::trait::accu_< A >::has_stop
+
+/// Shortcut to the accumulator property about behavior when pixel is given as take() value
+/// Used for instance in mln::canvas::morpho::leveling
+# define mln_trait_accu_when_pix(A) typename mln::trait::accu_< A >::when_pix
+
+namespace mln {
+
+ namespace trait {
+
+ namespace accu {
+
+ // Basic accumulators properties
+
+ struct has_untake
+ {
+ struct any { protected: any() {}; };
+
+ struct no : any { std::string name() const { return "has_untake::no"; } };
+
+ struct yes : any { std::string name() const { return "has_untake::yes"; } };
+ };
+
+ struct has_stop
+ {
+ struct any { protected: any() {}; };
+
+ struct no : any { std::string name() const { return "has_setvalue::no"; } };
+
+ struct yes : any { std::string name() const { return "has_stop::yes"; } };
+ };
+
+ struct has_setvalue
+ {
+ struct any { protected: any() {}; };
+
+ struct no : any { std::string name() const { return "has_setvalue::no"; } };
+
+ struct yes : any { std::string name() const { return "has_setvalue::yes"; } };
+ };
+
+ // Morphological accumulators properties
+ struct when_pix
+ {
+ struct any { protected: any() {}; };
+
+ struct use_v : any { std::string name() const { return "when_pix::use_v"; } };
+
+ struct use_p : any { std::string name() const { return "when_pix::use_p"; } };
+
+ struct use_pix : any { std::string name() const { return "when_pix::use_pix"; } };
+
+ struct not_ok : any { std::string name() const { return "when_pix::not_ok"; } };
+ };
+
+ } // end of namespace mln::trait::accu
+
+ template <typename A>
+ struct undefined_accu_
+ {
+ // general
+ typedef undef has_untake;
+ typedef undef has_stop;
+ typedef undef has_setvalue;
+
+ // morpho
+ typedef accu::when_pix::not_ok when_pix;
+ // FIXME: should default be undef ?
+ };
+
+ template <typename A>
+ struct accu_ : undefined_accu_<A>
+ {
+ };
+
+ } // end of namespace mln::trait
+
+ namespace canvas {
+
+ namespace morpho {
+
+ namespace impl {
+
+ namespace generic {
+
+ template <typename I, template <typename P> class A>
+ inline
+ void
+ leveling(const Image<I>& input,
+ Accumulator< A< util::pix<I> > >& acc)
+ {
+ const I& ima = exact(input);
+ A< util::pix<I> >& a = exact(acc);
+
+ mln_piter(I) p(ima.domain());
+
+ for_all(p)
+ a.take(mln::make::pix(ima, p));
+ }
+
+ } // end of namespace mln::canvas::morpho::impl::generic
+
+ // fast implementation (only on values from pixter)
+ template <typename I, template <typename P> class A>
+ inline
+ void
+ leveling_fastest(const Image<I>& input,
+ Accumulator< A< util::pix<I> > >& acc)
+ {
+ const I& ima = exact(input);
+ A< util::pix<I> >& a = exact(acc);
+
+ mln_pixter(const I) px(ima);
+
+ for_all(px)
+ a.take(px.val());
+ }
+
+ } // end of namespace mln::canvas::morpho::impl
+
+ namespace internal {
+
+ template <typename I, typename A>
+ inline
+ void
+ leveling_dispatch(metal::false_,
+ const Image<I>& input,
+ Accumulator<A>& acc)
+ {
+ impl::generic::leveling(input, acc);
+ }
+
+ template <typename I, typename A>
+ inline
+ void
+ leveling_dispatch(metal::true_,
+ const Image<I>& input,
+ Accumulator<A>& acc)
+ {
+ impl::leveling_fastest(input, acc);
+ }
+
+ template <typename I, typename A>
+ inline
+ void
+ leveling_dispatch(const Image<I>& input,
+ Accumulator<A>& acc)
+ {
+ enum {
+ test = mlc_equal(mln_trait_image_speed(I),
+ trait::image::speed::fastest)::value
+ &&
+ mlc_equal(mln_trait_accu_when_pix(A),
+ trait::accu::when_pix::use_v)::value
+ };
+ internal::leveling_dispatch(metal::bool_<test>(),
+ input, acc);
+ }
+
+ } // end of namespace mln::canvas::morpho::internal
+
+ // Facade.
+ template <typename I, template <typename P> class A>
+ inline
+ void
+ leveling(const Image<I>& input,
+ Accumulator< A< util::pix<I> > >& acc)
+ {
+ internal::leveling_dispatch(input, acc);
+ }
+
+ } // end of namespace mln::canvas::morpho
+
+ } // end of namespace mln::canvas
+
+ namespace morpho {
+
+ namespace accu {
+
+ // MEAN ACCUMULATOR
+ namespace internal {
+
+ template <typename V>
+ struct sum_handling_pixels
+ { typedef mln_sum(V) ret; };
+
+ template <typename I>
+ struct sum_handling_pixels< util::pix<I> >
+ { typedef mln_sum(mln_value(I)) ret; };
+
+ } // end of namespace mln::morpho::accu::internal
+
+ template <typename T>
+ /// Morphological (i.e. for pixel and pixel values) accumulator calculating mean.
+ /// FIXME: is inclusion polyphormism really appliable ?
+ struct mean : public mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret>,
+ public Accumulator< mean<T> >
+ {
+ typedef mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret> super;
+
+ using super::operator typename super::result;
+ using super::take;
+
+ void take(const mean<T>& m);
+ };
+
+ template <typename I>
+ struct mean< util::pix<I> > : public mean< mln_value(I) >,
+ public Accumulator< mean< util::pix<I> > >
+ {
+ typedef mean< mln_value(I) > super;
+ typedef util::pix<I> argument;
+
+ using super::operator typename super::result;
+ using super::take;
+
+ void take(const argument& t);
+ void take(const mean< util::pix<I> >& m);
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename T>
+ inline
+ void mean<T>::take(const mean<T>& m)
+ {
+ this->super::take(m);
+ }
+
+ template <typename I>
+ inline
+ void mean< util::pix<I> >::take(const mean< util::pix<I> >::argument& t)
+ {
+ this->mean< mln_value(I) >::take(t.v());
+ }
+
+ template <typename I>
+ inline
+ void mean< util::pix<I> >::take(const mean< util::pix<I> >& m)
+ {
+ this->super::take(m);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ // FROM mln::accu:: TO mln::morpho::acu::
+
+ template <template <typename T> class A>
+ struct from_mln_accu
+ {
+ template <typename T>
+ struct ret;
+
+ template <typename I>
+ struct ret< util::pix<I> > : public A< mln_value(I) >,
+ public Accumulator< ret< util::pix<I> > >
+ {
+ typedef A< mln_value(I) > super;
+ typedef typename super::result result;
+
+ typedef util::pix<I> argument;
+
+ using super::take;
+
+ void take(const argument& t);
+ void take(const ret< util::pix<I> >& m);
+ };
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <template <typename T> class A>
+ template <typename I>
+ inline
+ void from_mln_accu<A>::ret< util::pix<I> >::take(const from_mln_accu<A>::ret< util::pix<I> >& m)
+ {
+ this->super::take(m);
+ }
+
+ template <template <typename T> class A>
+ template <typename I>
+ inline
+ void from_mln_accu<A>::ret< util::pix<I> >::take(const from_mln_accu<A>::ret< util::pix<I> >::argument& t)
+ {
+ this->A< mln_value(I) >::take(t.v());
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho::accu
+
+ } // end of namespace mln::morpho
+
+ namespace trait {
+
+ template <typename I>
+ struct accu_< morpho::accu::mean< util::pix<I> > > :
+ public undefined_accu_ < morpho::accu::mean< util::pix<I> > >
+ {
+ typedef accu::when_pix::use_v when_pix;
+ };
+
+ template <template <typename T> class A, typename I>
+ struct accu_< morpho::accu::from_mln_accu < A > :: ret < I > >
+ {
+ typedef accu::when_pix::use_v when_pix;
+ };
+ } // end of namespace mln::trait
+
+} // end of namespace mln
+
+# include <mln/accu/all.hh>
+# include <mln/core/image/image2d.hh>
+
+# include <mln/debug/iota.hh>
+# include <mln/debug/println.hh>
+# include <mln/core/var.hh>
+# include <mln/util/timer.hh>
+int main()
+{
+ using namespace mln;
+ typedef image2d<int> I;
+
+ I ima(1000, 1000);
+ morpho::accu::from_mln_accu<accu::min>::ret<util::pix<I> > acc;
+
+ float elapsed;
+ mln::util::timer chrono;
+
+ debug::iota(ima);
+ std::cout << "50 mean of a 1000x1000 image2d<int>" << std::endl;
+
+ acc.init();
+ chrono.start();
+ for (int i = 0; i < 50; i++)
+ mln::canvas::morpho::leveling(ima, acc);
+ elapsed = chrono.stop();
+
+ std::cout << "(auto) " << elapsed << "s : " << acc.to_result() << std::endl;
+
+ acc.init();
+ chrono.start();
+ for (int i = 0; i < 50; i++)
+ mln::canvas::morpho::impl::generic::leveling(ima, acc);
+ elapsed = chrono.stop();
+
+ std::cout << "(generic) " << elapsed << "s : " << acc.to_result() << std::endl;
+
+ acc.init();
+ chrono.start();
+ for (int i = 0; i < 50; i++)
+ mln::canvas::morpho::impl::leveling_fastest(ima, acc);
+ elapsed = chrono.stop();
+
+ std::cout << "(fast) " << elapsed << "s : " << acc.to_result() << std::endl;
+}
Index: trunk/milena/sandbox/fred/old/connected_filter.hh
===================================================================
--- trunk/milena/sandbox/fred/old/connected_filter.hh (revision 0)
+++ trunk/milena/sandbox/fred/old/connected_filter.hh (revision 3415)
@@ -0,0 +1,123 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CANVAS_MORPHO_CONNECTED_FILTER_HH
+# define MLN_CANVAS_MORPHO_CONNECTED_FILTER_HH
+
+/// \file mln/canvas/morpho/connected_filter.hh
+///
+/// Connected filters dispatch (algebraic & leveling filters).
+///
+
+# include "leveling_filter.hh"
+# include <mln/canvas/morpho/algebraic_filter.hh>
+# include <mln/trait/accumulators.hh>
+
+namespace mln {
+ namespace canvas {
+ namespace morpho {
+
+ // Facade Fwd Declaration
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ connected_filter(const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda, bool increasing);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // Dispatch.
+ namespace internal
+ {
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ connected_filter_dispatch(mln::trait::accumulator::when_pix::use_none,
+ const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing)
+ {
+ return algebraic_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ connected_filter_dispatch(mln::trait::accumulator::when_pix::use_p,
+ const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing)
+ {
+ return algebraic_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ connected_filter_dispatch(mln::trait::accumulator::when_pix::use_v,
+ const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing)
+ {
+ return leveling_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ connected_filter_dispatch(mln::trait::accumulator::when_pix::use_pix,
+ const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing)
+ {
+ return leveling_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ } // end of namespace mln::canvas::morpho::internal
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ // Facade.
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ connected_filter(const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda, bool increasing)
+ {
+ return internal::connected_filter_dispatch(mln_trait_accu_when_pix(A)(),
+ input, nbh, a, lambda, increasing);
+ }
+
+
+ } // end of namespace mln::canvas::morpho
+ } // end of namespace mln::canvas
+} // end of namespace mln
+
+
+#endif // ! MLN_CANVAS_MORPHO_CONNECTED_FILTER_HH
Index: trunk/milena/sandbox/fred/old/leveling_filter.hh
===================================================================
--- trunk/milena/sandbox/fred/old/leveling_filter.hh (revision 0)
+++ trunk/milena/sandbox/fred/old/leveling_filter.hh (revision 3415)
@@ -0,0 +1,381 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CANVAS_MORPHO_LEVELING_FILTER_HH
+# define MLN_CANVAS_MORPHO_LEVELING_FILTER_HH
+
+/// \file mln/canvas/morpho/leveling_filter.hh
+///
+/// Apply leveling connected filter to images.
+///
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/concept/accumulator.hh>
+
+# include <mln/data/fill.hh>
+# include <mln/extension/adjust_fill.hh>
+
+# include <mln/level/sort_psites.hh>
+# include <mln/level/sort_offsets.hh>
+
+
+
+
+/*# include <mln/data/fill.hh>
+# include <mln/literal/zero.hh>
+# include <mln/convert/to_upper_window.hh>
+# include <mln/extension/adjust_fill.hh>
+# include <mln/util/pix.hh>
+*/
+
+namespace mln {
+ namespace canvas {
+ namespace morpho {
+
+ // Facade Fwd Declaration
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter(const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // Implementations.
+
+ namespace impl {
+
+ namespace generic {
+
+ // Generic Version
+
+ template <typename I>
+ static inline
+ mln_psite(I)
+ find_root(I& parent, const mln_psite(I) & x)
+ {
+ if (parent(x) == x)
+ return x;
+ else
+ return parent(x) = find_root(parent, parent(x));
+ }
+
+ template <typename I, typename N, typename S, typename A>
+ mln_concrete(I)
+ leveling_filter(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ const Site_Set<S>& s_,
+ const Accumulator<A>& a_, const typename A::result& lambda)
+ {
+ trace::entering("canvas::morpho::impl::generic::leveling_filter");
+ // FIXME: Test?!
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+ const S& s = exact(s_);
+ (void)a_; // To avoid warning at compilation
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ // Local type.
+ typedef mln_psite(I) P;
+
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, bool) activity;
+ mln_ch_value(I, P) parent;
+ mln_ch_value(I, A) data;
+
+ // Initialization.
+ {
+ initialize(deja_vu, input);
+ mln::data::fill(deja_vu, false);
+ initialize(activity, input);
+ mln::data::fill(activity, true);
+ initialize(parent, input);
+ initialize(data, input);
+ //a.init(); // init required.
+ }
+
+ // First pass.
+ {
+ mln_fwd_piter(S) p(s); // s required.
+ mln_niter(N) n(nbh, p);
+
+ for_all(p)
+ {
+ // Make set.
+ {
+ parent(p) = p;
+ data(p).take_as_init(make::pix(input, p));
+ }
+
+ for_all(n)
+ if (input.domain().has(n) && deja_vu(n))
+ {
+ //do_union(n, p);
+ P r = find_root(parent, n);
+ if (r != p)
+ {
+ if (input(r) == input(p) || (activity(r) && (data(r) < lambda))) // Equiv(r, p)
+ // Either a flat zone or the component of r is still growing.
+ {
+ /* FIXME: Same remark as above concerning the
+ initialization of data(p); instead of
+
+ data(p).take(data(r));
+
+ we should (or could) have
+
+ unite_data(p, r);
+
+ so as to keep the generic aspect of this canvas
+ (as long as the set of acceptable types for the
+ template parameter A is not bound). */
+ data(p).take(data(r));
+ parent(r) = p;
+ if (activity(r) == false)
+ activity(p) = false;
+ }
+ else
+ {
+ activity(p) = false;
+ }
+ }
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ // Second pass.
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ if (parent(p) == p) // p is root.
+ output(p) = input(p);
+ else
+ output(p) = output(parent(p));
+ }
+
+ trace::exiting("canvas::morpho::impl::generic::leveling_filter");
+ return output;
+ }
+
+ } // end of namespace mln::canvas::morpho::impl::generic
+
+
+ // Fastest version.
+
+
+ template <typename I>
+ inline
+ unsigned
+ find_root_fastest(I& parent, unsigned x)
+ {
+ if (parent.element(x) == x)
+ return x;
+ else
+ return parent.element(x) = find_root_fastest(parent, parent.element(x));
+ }
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter_fastest(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ const util::array<unsigned>& s,
+ const Accumulator<A>& a_, const typename A::result& lambda)
+ {
+ trace::entering("canvas::morpho::impl::leveling_fastest");
+
+ // FIXME: Tests?
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ // Local type.
+ typedef mln_psite(I) P;
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, bool) activity;
+ mln_ch_value(I, unsigned) parent;
+ mln_ch_value(I, A) data;
+
+ // Initialization.
+ {
+ initialize(deja_vu, input);
+ mln::data::fill(deja_vu, false);
+ initialize(activity, input);
+ mln::data::fill(activity, true);
+ initialize(parent, input);
+ mln::data::fill(parent, 0);
+ initialize(data, input);
+ }
+
+ util::array<int> dp = offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+ const unsigned n_points = s.nelements();
+
+ // First pass.
+ {
+
+ for (unsigned i = 0; i < n_points; ++i)
+ {
+ unsigned p = s[i]; // An offset.
+
+ // Make set.
+ parent.element(p) = p;
+ data.element(p).take_as_init(input.element(p));
+
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+ if (!deja_vu.element(n))
+ continue;
+
+ unsigned r = find_root_fastest(parent, n);
+ if (r != p)
+ {
+ if (input.element(r) == input.element(p)
+ || (activity.element(r)
+ && (data.element(r) < lambda)))
+ {
+ data.element(p).take(data.element(r));
+ parent.element(r) = p;
+ if (activity.element(r) == false)
+ activity.element(p) = false;
+ }
+ else
+ activity.element(p) = false;
+ }
+ }
+
+ deja_vu.element(p) = true;
+ }
+
+ }
+
+ // Second pass.
+ {
+ for (int i = n_points - 1; i >= 0 ; --i)
+ {
+ unsigned p = s[i];
+ if (parent.element(p) == p) // p is root.
+ output.element(p) = input.element(p);
+ else
+ output.element(p) = output.element(parent.element(p));
+ }
+ }
+
+ trace::exiting("canvas::morpho::impl::leveling_fastest");
+ return output;
+ }
+
+ } // end of namespace mln::canvas::morpho::impl
+
+ // Dispatch.
+ namespace internal
+ {
+
+ // Leveling
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter_dispatch(metal::false_,
+ const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing)
+ {
+ p_array < mln_psite(I) > s =
+ increasing ?
+ level::sort_psites_increasing(input) :
+ level::sort_psites_decreasing(input);
+ return impl::generic::leveling_filter(input, nbh, s, a, lambda);
+ }
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter_dispatch(metal::true_,
+ const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing)
+ {
+ util::array<unsigned> s =
+ increasing ?
+ level::sort_offsets_increasing(input) :
+ level::sort_offsets_decreasing(input);
+ return impl::leveling_filter_fastest(input, nbh, s, a, lambda);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ leveling_filter_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda, bool increasing)
+ {
+ enum
+ {
+ test = mlc_equal(mln_trait_image_speed(I),
+ trait::image::speed::fastest)::value
+ && mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_v)::value
+ && mln_is_simple_neighborhood(N)::value
+ };
+ return leveling_filter_dispatch(metal::bool_<test>(),
+ input, nbh, a, lambda, increasing);
+ }
+
+ } // end of namespace mln::canvas::morpho::internal
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ // Facade.
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ leveling_filter(const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing)
+ {
+ //FIXME: Do we need to check input validity ?
+ return internal::leveling_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ } // end of namespace mln::canvas::morpho
+ } // end of namespace mln::canvas
+} // end of namespace mln
+
+
+#endif // ! MLN_CANVAS_MORPHO_LEVELING_FILTER_HH
Index: trunk/milena/sandbox/fred/old/leveling.cc
===================================================================
--- trunk/milena/sandbox/fred/old/leveling.cc (revision 0)
+++ trunk/milena/sandbox/fred/old/leveling.cc (revision 3415)
@@ -0,0 +1,47 @@
+
+
+#include <mln/core/image/image2d.hh>
+#include <mln/io/pgm/all.hh>
+#include <mln/util/timer.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include "mean.hh"
+#include "leveling_filter.hh"
+
+int main(int argc, char** argv)
+{
+ using namespace mln;
+ using value::int_u8;
+
+ std::cout << "Leveling filter test" << std::endl;
+
+ typedef mln::image2d<int_u8> I;
+ I lena;
+
+ float elapsed;
+ mln::util::timer chrono;
+ mln::morpho::attribute::mean<I> c;
+ int lambda = atoi(argv[1]);
+
+ mln::io::pgm::load(lena, "../../img/lena.pgm");
+ I out;
+
+ chrono.start();
+ out = mln::canvas::morpho::leveling_filter(lena, c4(), c, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(auto) " << elapsed << "s" << std::endl;
+ mln::io::pgm::save(out, "auto.pgm");
+
+ chrono.start();
+ out = mln::canvas::morpho::internal::leveling_filter_dispatch(mln::metal::true_(), lena, c4(), c, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(fast) " << elapsed << "s" << std::endl;
+
+ mln::io::pgm::save(out, "fast.pgm");
+
+ chrono.start();
+ out = mln::canvas::morpho::internal::leveling_filter_dispatch(mln::metal::false_(), lena, c4(), c, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(slow) " << elapsed << "s" << std::endl;
+
+ mln::io::pgm::save(out, "slow.pgm");
+}
Index: trunk/milena/sandbox/fred/old/closing_area.cc
===================================================================
--- trunk/milena/sandbox/fred/old/closing_area.cc (revision 0)
+++ trunk/milena/sandbox/fred/old/closing_area.cc (revision 3415)
@@ -0,0 +1,50 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// 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 tests/morpho/closing_area.cc
+///
+/// Test on mln::morpho::closing_area.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/morpho/closing_area.hh>
+
+int main(int argc, char **argv)
+{
+ using namespace mln;
+ using value::int_u8;
+
+ image2d<int_u8> lena;
+ io::pgm::load(lena, "../../img/lena.pgm");
+ io::pgm::save(morpho::closing_area(lena, c4(), atoi(argv[1])), "out.pgm");
+}
Index: trunk/milena/sandbox/fred/old/value_wrapper.hh
===================================================================
--- trunk/milena/sandbox/fred/old/value_wrapper.hh (revision 0)
+++ trunk/milena/sandbox/fred/old/value_wrapper.hh (revision 3415)
@@ -0,0 +1,188 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MORPHO_ATTRIBUTE_VALUE_WRAPPER_HH
+# define MLN_MORPHO_ATTRIBUTE_VALUE_WRAPPER_HH
+
+/// \file mln/morpho/attribute/volume.hh
+///
+/// Transform an accumulator to a value (when_pix::use_v) accumulator.
+
+# include <mln/accu/internal/base.hh>
+# include <mln/util/pix.hh>
+
+# define mln_morpho_attribute_use_v_(T) mln::morpho::attribute::value_wrapper< T >
+# define mln_morpho_attribute_use_v(T) mln::morpho::attribute::value_wrapper< T >
+
+namespace mln
+{
+
+ // Forward declaration.
+ namespace morpho {
+ namespace attribute {
+ template <typename T> class value_wrapper;
+ }
+ }
+
+
+ // Traits.
+
+ namespace trait
+ {
+
+ template <typename A>
+ struct accumulator_< morpho::attribute::value_wrapper<A> >
+ {
+ typedef accumulator::has_untake::no has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
+
+ } // end of namespace mln::trait
+
+ namespace morpho
+ {
+
+ namespace attribute
+ {
+
+ /// Value wrapper accumulator meta-class.
+ ///
+ /// The parameter \p A is the base accumulator to wrap.
+ template <typename A>
+ struct value_wrapper
+ : public mln::accu::internal::base< typename A::result , value_wrapper<A> >
+ {
+ typedef typename A::argument argument;
+ typedef typename A::result result;
+
+ value_wrapper();
+
+ /// Manipulators.
+ /// \{
+ void init();
+
+ void take(const argument& v);
+ template <typename I>
+ void take(const util::pix<I>& px);
+ void take(const value_wrapper<A>& other);
+
+ void take_as_init(const argument& v);
+ template <typename I>
+ void take_as_init(const util::pix<I>& px);
+ /// \}
+
+ /// Get the value of the accumulator.
+ result to_result() const;
+
+ /// Check whether this accu is able to return a result.
+ bool is_valid() const;
+
+ protected:
+ /// Delegatee accumulator.
+ A accu_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename A>
+ value_wrapper<A>::value_wrapper()
+ : accu_()
+ {
+ }
+
+ template <typename A>
+ void
+ value_wrapper<A>::init()
+ {
+ accu_.init();
+ }
+
+ template <typename A>
+ void
+ value_wrapper<A>::take(const argument& v)
+ {
+ accu_.take(v);
+ }
+
+ template <typename A>
+ template <typename I>
+ void
+ value_wrapper<A>::take(const util::pix<I>& px)
+ {
+ take(px.v());
+ }
+
+ template <typename A>
+ void
+ value_wrapper<A>::take(const value_wrapper<A>& other)
+ {
+ accu_.take(other.accu_);
+ }
+
+ template <typename A>
+ void
+ value_wrapper<A>::take_as_init(const argument& v)
+ {
+ accu_.take_as_init(v);
+ }
+
+ template <typename A>
+ template <typename I>
+ void
+ value_wrapper<A>::take_as_init(const util::pix<I>& px)
+ {
+ accu_.take_as_init(px);
+ }
+
+ template <typename A>
+ typename value_wrapper<A>::result
+ value_wrapper<A>::to_result() const
+ {
+ return accu_.to_result();
+ }
+
+ template <typename A>
+ bool
+ value_wrapper<A>::is_valid() const
+ {
+ return accu_.is_valid();
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho::attribute
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_ATTRIBUTE_VALUE_WRAPPER_HH
Index: trunk/milena/sandbox/fred/old/accu_trait.hh
===================================================================
--- trunk/milena/sandbox/fred/old/accu_trait.hh (revision 0)
+++ trunk/milena/sandbox/fred/old/accu_trait.hh (revision 3415)
@@ -0,0 +1,94 @@
+#ifndef MLN_TRAIT_ACCU_HH
+# define MLN_TRAIT_ACCU_HH
+
+# include <string>
+# include <mln/trait/undef.hh>
+
+/// Shortcut to the accumulator property about untake method disponibility
+# define mln_trait_accu_has_untake(A) typename mln::trait::accu_< A >::has_untake
+
+/// Shortcut to the accumulator property about setvalue method disponibility
+# define mln_trait_accu_has_setvalue(A) typename mln::trait::accu_< A >::has_setvalue
+
+/// Shortcut to the accumulator property about stop method disponibility
+# define mln_trait_accu_has_stop(A) typename mln::trait::accu_< A >::has_stop
+
+/// Shortcut to the accumulator property about behavior when pixel is given as take() value
+/// Used for instance in mln::canvas::morpho::leveling
+# define mln_trait_accu_when_pix(A) typename mln::trait::accu_< A >::when_pix
+
+namespace mln {
+
+ namespace trait {
+
+ namespace accu {
+
+ // Basic accumulators properties
+
+ struct has_untake
+ {
+ struct any { protected: any() {}; };
+
+ struct no : any { std::string name() const { return "has_untake::no"; } };
+
+ struct yes : any { std::string name() const { return "has_untake::yes"; } };
+ };
+
+ struct has_stop
+ {
+ struct any { protected: any() {}; };
+
+ struct no : any { std::string name() const { return "has_setvalue::no"; } };
+
+ struct yes : any { std::string name() const { return "has_stop::yes"; } };
+ };
+
+ struct has_setvalue
+ {
+ struct any { protected: any() {}; };
+
+ struct no : any { std::string name() const { return "has_setvalue::no"; } };
+
+ struct yes : any { std::string name() const { return "has_setvalue::yes"; } };
+ };
+
+ // Morphological accumulators properties
+ struct when_pix
+ {
+ struct any { protected: any() {}; };
+
+ struct use_only_v : any { std::string name() const { return "when_pix::use_only_v"; } };
+
+ struct use_only_p : any { std::string name() const { return "when_pix::use_only_p"; } };
+
+ struct use_pix : any { std::string name() const { return "when_pix::use_pix"; } };
+
+ struct use_whatever : any { std::string name() const { return "when_pix::use_whatever"; } };
+
+ struct not_ok : any { std::string name() const { return "when_pix::not_ok"; } };
+ };
+
+ } // end of namespace mln::trait::accu
+
+ template <typename A>
+ struct undefined_accu_
+ {
+ // general
+ typedef undef has_untake;
+ typedef undef has_stop;
+ typedef undef has_setvalue;
+
+ // morpho
+ typedef accu::when_pix::use_pix when_pix;
+ };
+
+ template <typename A>
+ struct accu_ : public undefined_accu_<A>
+ {
+ };
+
+ } // end of namespace mln::trait
+
+} // end of namespace mln
+
+#endif /* !MLN_TRAIT_ACCU_HH */
Index: trunk/milena/sandbox/fred/old/algebraic.cc
===================================================================
--- trunk/milena/sandbox/fred/old/algebraic.cc (revision 0)
+++ trunk/milena/sandbox/fred/old/algebraic.cc (revision 3415)
@@ -0,0 +1,406 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CANVAS_ALGEBRAIC_HH
+# define MLN_CANVAS_ALGEBRAIC_HH
+
+/// \file mln/canvas/algebraic.hh
+///
+/// Apply algebraic connected filter to images.
+///
+/// \todo Test inputs validity.
+
+# include <mln/core/concept/image.hh>
+# include <mln/data/fill.hh>
+# include <mln/literal/zero.hh>
+# include <mln/convert/to_upper_window.hh>
+# include <mln/extension/adjust_fill.hh>
+
+# include <mln/level/sort_psites.hh>
+# include <mln/level/sort_offsets.hh>
+# include <mln/core/alias/neighb2d.hh>
+
+# include "../edwin/accu_trait.hh"
+# include "../edwin/card.hh"
+
+namespace mln
+{
+
+ namespace canvas
+ {
+
+ template < typename I, typename N, typename A, typename L>
+ mln_concrete(I)
+ algebraic(const Image<I>& input, const Neighborhood<N>& nbh,
+ Accumulator<A>& a, L lambda, bool increasing);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // Implementations.
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I>
+ static inline
+ mln_psite(I)
+ find_root(I& parent, const mln_psite(I) & x)
+ {
+ if (parent(x) == x)
+ return x;
+ else
+ return parent(x) = find_root(parent, parent(x));
+ }
+
+ template < typename I, typename N, typename S, typename A, typename L>
+ mln_concrete(I)
+ algebraic(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ const Site_Set<S>& s_, const Accumulator<A>& a_, L lambda)
+ {
+ trace::entering("canvas::impl::generic::algebraic");
+
+ // FIXME: Test?!
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+ const S& s = exact(s_);
+ //const A& a = exact(a_);
+ (void)a_;
+ // Local type.
+ typedef mln_psite(I) P;
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, bool) activity;
+ mln_ch_value(I, P) parent;
+ mln_ch_value(I, A) data;
+
+ // Initialization.
+ {
+ initialize(deja_vu, input);
+ mln::data::fill(deja_vu, false);
+ initialize(activity, input);
+ mln::data::fill(activity, true);
+ initialize(parent, input);
+ initialize(data, input);
+// a.init(); // init required.
+ }
+
+ // First pass.
+ {
+ mln_fwd_piter(S) p(s); // s required.
+ mln_niter(N) n(nbh, p);
+
+ for_all(p)
+ {
+ // Make set.
+ {
+ parent(p) = p;
+ data(p).take_as_init(p);
+ }
+
+ for_all(n)
+ if (input.domain().has(n) && deja_vu(n))
+ {
+ //do_union(n, p);
+ P r = find_root(parent, n);
+ if (r != p)
+ {
+ if (input(r) == input(p) || (activity(r) && (data(r) < lambda))) // Equiv(r, p)
+ // Either a flat zone or the component of r is still growing.
+ {
+ /* FIXME: Same remark as above concerning the
+ initialization of data(p); instead of
+
+ data(p).take(data(r));
+
+ we should (or could) have
+
+ unite_data(p, r);
+
+ so as to keep the generic aspect of this canvas
+ (as long as the set of acceptable types for the
+ template parameter A is not bound). */
+ data(p).take(data(r));
+ parent(r) = p;
+ if (activity(r) == false)
+ activity(p) = false;
+ }
+ else
+ {
+ activity(p) = false;
+ }
+ }
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ // Second pass.
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ if (parent(p) == p) // p is root.
+ output(p) = input(p);
+ else
+ output(p) = output(parent(p));
+ }
+
+ trace::exiting("canvas::morpho::impl::generic::algebraic");
+ return output;
+ }
+
+ } // end of namespace mln::canvas::impl::generic
+
+ // Fastest version.
+ template <typename I>
+ inline
+ unsigned
+ find_root_fastest(I& parent, unsigned x)
+ {
+ if (parent.element(x) == x)
+ return x;
+ else
+ return parent.element(x) = find_root_fastest(parent, parent.element(x));
+ }
+
+ template < typename I, typename N, typename A, typename L>
+ mln_concrete(I)
+ algebraic_fastest(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ const util::array<unsigned>& s, const Accumulator<A>& a_, L lambda)
+ {
+ trace::entering("canvas::impl::algebraic_fastest");
+
+ // FIXME: Tests?
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ // Local type.
+ typedef mln_psite(I) P;
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, bool) activity;
+ mln_ch_value(I, unsigned) parent;
+ mln_ch_value(I, A) data;
+
+ // Initialization.
+ {
+ initialize(deja_vu, input);
+ mln::data::fill(deja_vu, false);
+ initialize(activity, input);
+ mln::data::fill(activity, true);
+ initialize(parent, input);
+ mln::data::fill(parent, 0);
+ initialize(data, input);
+ }
+
+ util::array<int> dp = offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+ const unsigned n_points = s.nelements();
+
+ // First pass.
+ {
+
+ for (unsigned i = 0; i < n_points; ++i)
+ {
+ unsigned p = s[i]; // An offset.
+
+ // Make set.
+ parent.element(p) = p;
+ data.element(p).take_as_init();
+
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+ if (!deja_vu.element(n))
+ continue;
+
+ unsigned r = find_root_fastest(parent, n);
+ if (r != p)
+ {
+ if (input.element(r) == input.element(p)
+ || (activity.element(r)
+ && (data.element(r) < lambda)))
+ {
+ data.element(p).take(data.element(r));
+ parent.element(r) = p;
+ if (activity.element(r) == false)
+ activity.element(p) = false;
+ }
+ else
+ activity.element(p) = false;
+ }
+ }
+
+ deja_vu.element(p) = true;
+ }
+
+ }
+
+ // Second pass.
+ {
+ for (int i = n_points - 1; i >= 0 ; --i)
+ {
+ unsigned p = s[i];
+ if (parent.element(p) == p) // p is root.
+ output.element(p) = input.element(p);
+ else
+ output.element(p) = output.element(parent.element(p));
+ }
+ }
+
+ trace::exiting("canvas::impl::algebraic_fastest");
+ return output;
+ }
+
+ } // end of namespace mln::canvas::impl
+
+ // Dispatch.
+ namespace internal
+ {
+
+ // Algebraic
+ template < typename I, typename N, typename A, typename L>
+ mln_concrete(I)
+ algebraic_dispatch(metal::false_,
+ const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, L lambda, bool increasing)
+ {
+ p_array < mln_psite(I) > s =
+ increasing ?
+ level::sort_psites_increasing(input) :
+ level::sort_psites_decreasing(input);
+ return impl::generic::algebraic(input, nbh, s, a, lambda);
+ }
+
+ template < typename I, typename N, typename A, typename L>
+ mln_concrete(I)
+ algebraic_dispatch(metal::true_,
+ const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, L lambda, bool increasing)
+ {
+ util::array<unsigned> s =
+ increasing ?
+ level::sort_offsets_increasing(input) :
+ level::sort_offsets_decreasing(input);
+ return impl::algebraic_fastest(input, nbh, s, a, lambda);
+ }
+
+ template < typename I, typename N, typename A, typename L>
+ inline
+ mln_concrete(I)
+ algebraic_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, L lambda, bool increasing)
+ {
+ enum
+ {
+ test = mlc_equal(mln_trait_image_speed(I),
+ trait::image::speed::fastest)::value
+ && mlc_equal(mln_trait_accu_when_pix(A),
+ trait::accu::when_pix::use_whatever)::value
+ && mln_is_simple_neighborhood(N)::value
+ };
+ return algebraic_dispatch(metal::bool_<test>(),
+ input, nbh, a, lambda, increasing);
+ }
+
+
+ } // end of namespace mln::canvas::internal
+
+ // Facades.
+ template < typename I, typename N, typename A, typename L>
+ inline
+ mln_concrete(I)
+ algebraic(const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& a, L lambda, bool increasing)
+ {
+// FIXME: Do we need to check input validity ?
+ return internal::algebraic_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::canvas
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CANVAS_ALGEBRAIC_HH
+
+#include <mln/core/image/image2d.hh>
+#include <mln/io/pgm/all.hh>
+#include <mln/util/timer.hh>
+
+int main(int argc, char **argv)
+{
+ using namespace mln;
+ using value::int_u8;
+
+ std::cout << "Algebraic filter test, reference: closing_area" << std::endl;
+
+ typedef mln::image2d<int_u8> I;
+ I lena;
+
+ float elapsed;
+ mln::util::timer chrono;
+
+ mln::io::pgm::load(lena, "../../img/lena.pgm");
+ I out;
+ int lambda = atoi(argv[1]);
+
+ chrono.start();
+ out = mln::canvas::algebraic (lena, c4(), mln::morpho::accu::card<I>(), lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(auto) " << elapsed << "s" << std::endl;
+ mln::io::pgm::save(out, "auto.pgm");
+
+ chrono.start();
+ out = mln::canvas::internal::algebraic_dispatch(mln::metal::true_(), lena, c4(), mln::morpho::accu::card<I>(), lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(fast) " << elapsed << "s" << std::endl;
+
+ mln::io::pgm::save(out, "fast.pgm");
+
+ chrono.start();
+ out = mln::canvas::internal::algebraic_dispatch(mln::metal::false_(), lena, c4(), mln::morpho::accu::card<I>(), lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(slow) " << elapsed << "s" << std::endl;
+
+ mln::io::pgm::save(out, "slow.pgm");
+}
\ No newline at end of file
Index: trunk/milena/sandbox/fred/old/mean.hh
===================================================================
--- trunk/milena/sandbox/fred/old/mean.hh (revision 0)
+++ trunk/milena/sandbox/fred/old/mean.hh (revision 3415)
@@ -0,0 +1,202 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MORPHO_ATTRIBUTE_MEAN_HH
+# define MLN_MORPHO_ATTRIBUTE_MEAN_HH
+
+/// \file mln/morpho/attribute/mean.hh
+///
+/// Define an accumulator that computes the mean of a
+/// component.
+///
+
+# include <mln/accu/internal/base.hh>
+# include <mln/accu/mean.hh>
+# include <mln/util/pix.hh>
+
+namespace mln {
+
+ // Forward declaration.
+
+ namespace morpho {
+ namespace attribute {
+ template <typename I> class mean;
+ }
+ }
+
+ // Traits
+
+ namespace trait {
+ template <typename I>
+ struct accumulator_< morpho::attribute::mean<I> >
+ {
+ typedef accumulator::has_untake::no has_untake;
+ typedef accumulator::has_set_value::yes has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
+ }
+
+
+ namespace morpho {
+
+ namespace attribute {
+
+ namespace internal {
+
+ template <typename T, typename S>
+ struct sum_set_value : public mln::accu::sum<T, S>
+ {
+ void set_value(const S& s);
+ };
+
+ }
+
+ /// Morphological (i.e. for pixel and pixel values) accumulator calculating mean.
+ /// Valid for leveling algorithm.
+ template <typename I>
+ class mean: public mln::accu::internal::base<mln_sum(mln_value(I)), mean<I> >
+ {
+ public:
+ typedef util::pix<I> argument;
+ typedef mln_value(I) value;
+ typedef mln_sum(value) result;
+
+ mean();
+
+ /// Manipulators.
+ /// \{
+ void init();
+ void take(const value& v);
+ void take(const argument& t);
+ void take(const mean<I>& other);
+
+ void set_value(const result& r);
+ /// \}
+
+ /// Get the value of the accumulator.
+ result to_result() const;
+
+ /// Check whether this accu is able to return a result.
+ /// Always true here.
+ bool is_valid() const;
+
+ protected:
+
+ accu::count<value> count_;
+ internal::sum_set_value<value,result> sum_;
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal {
+
+ template <typename T, typename S>
+ void
+ sum_set_value<T, S>::set_value(const S& s)
+ {
+ this->s_ = s;
+ };
+
+ }
+
+ template <typename I>
+ inline
+ mean<I>::mean()
+ {
+ init();
+ }
+
+ template <typename I>
+ inline
+ void
+ mean<I>::init()
+ {
+ count_.init();
+ sum_.init();
+ }
+
+ template <typename I>
+ inline
+ void
+ mean<I>::take(const value& t)
+ {
+ count_.take(t);
+ sum_.take(t);
+ }
+
+ template <typename I>
+ inline
+ void
+ mean<I>::take(const argument& t)
+ {
+ take(t.v());
+ }
+
+ template <typename I>
+ inline
+ void
+ mean<I>::take(const mean<I>& other)
+ {
+ count_.take(other.count_);
+ sum_.take(other.sum_);
+ }
+
+ template <typename I>
+ void
+ mean<I>::set_value(const result& r)
+ {
+ sum_.set_value(r * count_.to_result());
+ };
+
+ template <typename I>
+ inline
+ typename mean<I>::result
+ mean<I>::to_result() const
+ {
+ unsigned n = count_.to_result();
+ return sum_.to_result() / n;
+ }
+
+ template <typename I>
+ inline
+ bool
+ mean<I>::is_valid() const
+ {
+ return count_.to_result() != 0;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho::attribute
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+#endif /* ! MLN_MORPHO_ATTRIBUTE_MEAN_HH */
1
0
* tests/core/routine/extend.cc,
* tests/extract/blue.cc,
* tests/extract/green.cc,
* tests/extract/red.cc,
* tests/labeling/blobs.cc,
* tests/morpho/artificial_line_graph_image_wst.cc,
* tests/morpho/elementary/gradient.cc,
* tests/morpho/elementary/gradient_external.cc,
* tests/morpho/elementary/gradient_internal.cc,
* tests/morpho/elementary/laplacian.cc,
* tests/morpho/lena_line_graph_image_wst1.cc,
* tests/morpho/lena_line_graph_image_wst2.cc,
* tests/morpho/skeleton_constrained.cc,
* tests/morpho/tree/compute_parent.cc,
* tests/pw/image.cc: Use the proper type for variables instead of
mln_VAR.
---
milena/ChangeLog | 23 ++++++++-
milena/tests/core/routine/extend.cc | 13 +++--
milena/tests/extract/blue.cc | 6 ++-
milena/tests/extract/green.cc | 6 ++-
milena/tests/extract/red.cc | 6 ++-
milena/tests/labeling/blobs.cc | 10 ++--
.../morpho/artificial_line_graph_image_wst.cc | 17 ++++--
milena/tests/morpho/elementary/gradient.cc | 43 ++++++++-------
.../tests/morpho/elementary/gradient_external.cc | 40 ++++++++-------
.../tests/morpho/elementary/gradient_internal.cc | 42 ++++++++-------
milena/tests/morpho/elementary/laplacian.cc | 15 +++---
milena/tests/morpho/lena_line_graph_image_wst1.cc | 13 +++--
milena/tests/morpho/lena_line_graph_image_wst2.cc | 15 ++++--
milena/tests/morpho/skeleton_constrained.cc | 52 +++++++++++++------
milena/tests/morpho/tree/compute_parent.cc | 54 ++++++++++++++++---
milena/tests/pw/image.cc | 9 ++-
16 files changed, 234 insertions(+), 130 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index fabb854..58919f4 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,8 +1,29 @@
2009-02-23 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Do not use mln_VAR in tests.
+
+ * tests/core/routine/extend.cc,
+ * tests/extract/blue.cc,
+ * tests/extract/green.cc,
+ * tests/extract/red.cc,
+ * tests/labeling/blobs.cc,
+ * tests/morpho/artificial_line_graph_image_wst.cc,
+ * tests/morpho/elementary/gradient.cc,
+ * tests/morpho/elementary/gradient_external.cc,
+ * tests/morpho/elementary/gradient_internal.cc,
+ * tests/morpho/elementary/laplacian.cc,
+ * tests/morpho/lena_line_graph_image_wst1.cc,
+ * tests/morpho/lena_line_graph_image_wst2.cc,
+ * tests/morpho/skeleton_constrained.cc,
+ * tests/morpho/tree/compute_parent.cc,
+ * tests/pw/image.cc: Use the proper type for variables instead of
+ mln_VAR.
+
+2009-02-23 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Fix ambiguity in morpho::elementary::gradient dispatch.
- * mln/morpho/elementary/gradient.hh: Ambiguity with images both
+ * mln/morpho/elementary/gradient.hh: Fix ambiguity with images both
fastest and logic.
2009-02-23 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/milena/tests/core/routine/extend.cc b/milena/tests/core/routine/extend.cc
index c6144af..93b2a0e 100644
--- a/milena/tests/core/routine/extend.cc
+++ b/milena/tests/core/routine/extend.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,10 +26,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/core/routine/extend.cc
- *
- * \brief Tests on mln::extend.
- */
+/// \file tests/core/routine/extend.cc
+///
+/// Tests on mln::extend.
#include <mln/core/var.hh>
@@ -58,7 +58,8 @@ int main()
debug::println(ima);
debug::println(extended_to(ima, bb));
- mln_VAR(ima_, extend(ima | make::box2d(2,2), 7));
+ typedef extension_val<const sub_image<image2d<int>, box2d> > ima_t_;
+ ima_t_ ima_ = extend(ima | make::box2d(2,2), 7);
debug::println(ima_);
debug::println(extended_to(ima_, BB));
diff --git a/milena/tests/extract/blue.cc b/milena/tests/extract/blue.cc
index 2748fa3..5c6ec69 100644
--- a/milena/tests/extract/blue.cc
+++ b/milena/tests/extract/blue.cc
@@ -33,12 +33,14 @@
int main()
{
using namespace mln;
+ using value::rgb8;
- image2d<value::rgb8> ima(2,2);
+ typedef image2d<rgb8> I;
+ I ima(2,2);
point2d p(1,1);
ima(p) = value::rgb8(200, 230, 240);
- mln_VAR(ima_blue, extract::blue(ima));
+ fun_image<meta::blue<rgb8>,I> ima_blue = extract::blue(ima);
mln_assertion(ima(p).blue() == ima_blue(p));
}
diff --git a/milena/tests/extract/green.cc b/milena/tests/extract/green.cc
index 59a8c28..adadc00 100644
--- a/milena/tests/extract/green.cc
+++ b/milena/tests/extract/green.cc
@@ -33,12 +33,14 @@
int main()
{
using namespace mln;
+ using value::rgb8;
- image2d<value::rgb8> ima(2,2);
+ typedef image2d<rgb8> I;
+ I ima(2,2);
point2d p(1,1);
ima(p) = value::rgb8(200, 230, 240);
- mln_VAR(ima_green, extract::green(ima));
+ fun_image<meta::green<rgb8>,I> ima_green = extract::green(ima);
mln_assertion(ima(p).green() == ima_green(p));
}
diff --git a/milena/tests/extract/red.cc b/milena/tests/extract/red.cc
index de2facb..3bfb551 100644
--- a/milena/tests/extract/red.cc
+++ b/milena/tests/extract/red.cc
@@ -33,12 +33,14 @@
int main()
{
using namespace mln;
+ using value::rgb8;
- image2d<value::rgb8> ima(2,2);
+ typedef image2d<rgb8> I;
+ I ima(2,2);
point2d p(1,1);
ima(p) = value::rgb8(200, 230, 240);
- mln_VAR(ima_red, extract::red(ima));
+ fun_image<meta::red<rgb8>,I> ima_red = extract::red(ima);
mln_assertion(ima(p).red() == ima_red(p));
}
diff --git a/milena/tests/labeling/blobs.cc b/milena/tests/labeling/blobs.cc
index 549e3c4..7ba41d1 100644
--- a/milena/tests/labeling/blobs.cc
+++ b/milena/tests/labeling/blobs.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,10 +26,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/labeling/blobs.cc
- *
- * \brief Test on mln::labeling::blobs.
- */
+/// \file tests/labeling/blobs.cc
+///
+/// Test on mln::labeling::blobs.
#include <mln/core/image/image2d.hh>
#include <mln/io/pbm/load.hh>
diff --git a/milena/tests/morpho/artificial_line_graph_image_wst.cc b/milena/tests/morpho/artificial_line_graph_image_wst.cc
index 415ad87..d6434cf 100644
--- a/milena/tests/morpho/artificial_line_graph_image_wst.cc
+++ b/milena/tests/morpho/artificial_line_graph_image_wst.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -108,15 +109,17 @@ int main()
((r / square_length) % 2 == (c / square_length) % 2)
? mln_min(input_val_t)
: mln_max(input_val_t);
- std::cout << "nvertices = " << nrows * ncols << std::endl
- << "nedges = " << 2 * nrows * ncols - (nrows + ncols) << std::endl;
+ mln_assertion((nrows * ncols) == 10000);
+ mln_assertion((2 * nrows * ncols - (rows + ncols)) == 19800);
/*----------------.
| Line gradient. |
`----------------*/
// Line graph image.
- mln_VAR(lg_ima, morpho::line_gradient(input));
+ typedef pw::image<fun::i2v::array<input_val_t>, p_edges<util::graph,
+ fun::i2v::array< util::site_pair<point2d> > > > lg_ima_t;
+ lg_ima_t lg_ima = morpho::line_gradient(input);
/*------.
| WST. |
@@ -126,9 +129,11 @@ int main()
nbh_t nbh;
// Perform a Watershed Transform.
+ typedef pw::image<fun::i2v::array<unsigned>, p_edges<util::graph,
+ fun::i2v::array< util::site_pair<point2d> > > > wshed_t;
unsigned nbasins;
- mln_VAR(wshed, morpho::meyer_wst(lg_ima, nbh, nbasins));
- std::cout << "nbasins = " << nbasins << std::endl;
+ wshed_t wshed = morpho::meyer_wst(lg_ima, nbh, nbasins);
+ mln_assertion(nbasins == 1155);
/*---------.
| Output. |
diff --git a/milena/tests/morpho/elementary/gradient.cc b/milena/tests/morpho/elementary/gradient.cc
index d690c8e..02b9e20 100644
--- a/milena/tests/morpho/elementary/gradient.cc
+++ b/milena/tests/morpho/elementary/gradient.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,10 +26,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/morpho/elementary/gradient.cc
- *
- * \brief Test on mln::morpho::elementary::gradient.
- */
+/// \file tests/morpho/elementary/gradient.cc
+///
+/// Test on mln::morpho::elementary::gradient.
#include <mln/core/image/image2d.hh>
#include <mln/core/image/sub_image.hh>
@@ -41,33 +41,36 @@
#include <mln/morpho/elementary/gradient.hh>
-
int main()
{
using namespace mln;
using value::int_u8;
-// trace::quiet = false;
-
image2d<int_u8> ima(3, 3, 0);
debug::iota(ima);
- debug::println(ima);
-
- mln_VAR(b, ima.domain());
{
- mln_VAR(gra,
- morpho::elementary::gradient(ima | b, c4()));
- debug::println(gra);
+ int_u8 ref_[9] = { 3, 4, 4,
+ 6, 6, 6,
+ 4, 4, 3 };
+ image2d<int_u8> ref = make::image2d(ref_);
+
+ image2d<int_u8> gra = morpho::elementary::gradient(ima, c4());
+ mln_assertion(gra == ref);
}
- image2d<bool> msk(3, 3, 0);
- data::fill(msk, pw::value(ima) >= pw::cst(5u));
- debug::println(msk);
{
- mln_VAR(gra,
- morpho::elementary::gradient(msk | b, c4()));
- debug::println(gra);
+ bool ref_[9] = { 0, 1, 1,
+ 1, 1, 1,
+ 1, 0, 0 };
+ image2d<bool> ref = make::image2d(ref_);
+
+ image2d<bool> msk(3, 3, 0);
+ data::fill(msk, pw::value(ima) >= pw::cst(5u));
+
+ image2d<bool> gra = morpho::elementary::gradient(msk, c4());
+
+ mln_assertion(gra == ref);
}
}
diff --git a/milena/tests/morpho/elementary/gradient_external.cc b/milena/tests/morpho/elementary/gradient_external.cc
index 1a91ff4..bc064cc 100644
--- a/milena/tests/morpho/elementary/gradient_external.cc
+++ b/milena/tests/morpho/elementary/gradient_external.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,10 +26,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/morpho/elementary/gradient_external.cc
- *
- * \brief Test on mln::morpho::elementary::gradient_external.
- */
+/// \file tests/morpho/elementary/gradient_external.cc
+///
+/// Test on mln::morpho::elementary::gradient_external.
#include <mln/core/image/image2d.hh>
#include <mln/core/image/sub_image.hh>
@@ -47,27 +47,29 @@ int main()
using namespace mln;
using value::int_u8;
-// trace::quiet = false;
-
image2d<int_u8> ima(3, 3, 0);
debug::iota(ima);
- debug::println(ima);
-
- mln_VAR(b, ima.domain());
{
- mln_VAR(gra,
- morpho::elementary::gradient_external(ima | b, c4()));
- debug::println(gra);
+ int_u8 ref_[9] = { 3, 3, 3,
+ 3, 3, 3,
+ 1, 1, 0 };
+ image2d<int_u8> ref = make::image2d(ref_);
+
+ image2d<int_u8> gra = morpho::elementary::gradient_external(ima, c4());
+ mln_assertion(gra == ref);
}
- image2d<bool> msk(3, 3, 0);
- data::fill(msk, pw::value(ima) >= pw::cst(5u));
- debug::println(msk);
{
- mln_VAR(gra,
- morpho::elementary::gradient_external(msk | b, c4()));
- debug::println(gra);
+ bool ref_[9] = { 0, 1, 1,
+ 1, 0, 0,
+ 0, 0, 0 };
+ image2d<bool> ref = make::image2d(ref_);
+
+ image2d<bool> msk(3, 3, 0);
+ data::fill(msk, pw::value(ima) >= pw::cst(5u));
+ image2d<bool> gra = morpho::elementary::gradient_external(msk, c4());
+ mln_assertion(gra == ref);
}
}
diff --git a/milena/tests/morpho/elementary/gradient_internal.cc b/milena/tests/morpho/elementary/gradient_internal.cc
index 91b1c14..3e72d4e 100644
--- a/milena/tests/morpho/elementary/gradient_internal.cc
+++ b/milena/tests/morpho/elementary/gradient_internal.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,19 +26,18 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/morpho/elementary/gradient_internal.cc
- *
- * \brief Test on mln::morpho::elementary::gradient_internal.
- */
+/// \file tests/morpho/elementary/gradient_internal.cc
+///
+/// Test on mln::morpho::elementary::gradient_internal.
#include <mln/core/image/image2d.hh>
#include <mln/core/image/sub_image.hh>
#include <mln/core/alias/neighb2d.hh>
#include <mln/core/var.hh>
#include <mln/value/int_u8.hh>
+#include <mln/make/image2d.hh>
#include <mln/debug/iota.hh>
-#include <mln/debug/println.hh>
#include <mln/morpho/elementary/gradient_internal.hh>
@@ -47,27 +47,29 @@ int main()
using namespace mln;
using value::int_u8;
-// trace::quiet = false;
-
image2d<int_u8> ima(3, 3, 0);
debug::iota(ima);
- debug::println(ima);
-
- mln_VAR(b, ima.domain());
{
- mln_VAR(gra,
- morpho::elementary::gradient_internal(ima | b, c4()));
- debug::println(gra);
+ int_u8 ref_[9] = { 0, 1, 1,
+ 3, 3, 3,
+ 3, 3, 3 };
+ image2d<int_u8> ref = make::image2d(ref_);
+
+ image2d<int_u8> gra = morpho::elementary::gradient_internal(ima, c4());
+ mln_assertion(gra == ref);
}
- image2d<bool> msk(3, 3, 0);
- data::fill(msk, pw::value(ima) >= pw::cst(5u));
- debug::println(msk);
{
- mln_VAR(gra,
- morpho::elementary::gradient_internal(msk | b, c4()));
- debug::println(gra);
+ bool ref_[9] = { 0, 0, 0,
+ 0, 1, 1,
+ 1, 0, 0 };
+ image2d<bool> ref = make::image2d(ref_);
+
+ image2d<bool> msk(3, 3, 0);
+ data::fill(msk, pw::value(ima) >= pw::cst(5u));
+ image2d<bool> gra = morpho::elementary::gradient_internal(msk, c4());
+ mln_assertion(gra == ref);
}
}
diff --git a/milena/tests/morpho/elementary/laplacian.cc b/milena/tests/morpho/elementary/laplacian.cc
index 537abae..dbe9303 100644
--- a/milena/tests/morpho/elementary/laplacian.cc
+++ b/milena/tests/morpho/elementary/laplacian.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,10 +26,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/morpho/elementary/laplacian.cc
- *
- * \brief Test on mln::morpho::elementary::laplacian.
- */
+/// \file tests/morpho/elementary/laplacian.cc
+///
+/// Test on mln::morpho::elementary::laplacian.
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/neighb2d.hh>
@@ -46,13 +46,12 @@ int main()
using namespace mln;
using value::int_u8;
-// trace::quiet = false;
-
image2d<int_u8> ima(3, 3, 0);
debug::iota(ima);
debug::println(ima);
- mln_VAR(lap, morpho::elementary::laplacian(ima, c4()));
+ typedef image2d<int> lap_t;
+ lap_t lap = morpho::elementary::laplacian(ima, c4());
mln_assertion(lap.border() == 1);
debug::println(lap);
diff --git a/milena/tests/morpho/lena_line_graph_image_wst1.cc b/milena/tests/morpho/lena_line_graph_image_wst1.cc
index aa2d257..fee2d1c 100644
--- a/milena/tests/morpho/lena_line_graph_image_wst1.cc
+++ b/milena/tests/morpho/lena_line_graph_image_wst1.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -149,8 +150,8 @@ int main()
pe_t pe(g, edge_sites);
// Line graph image
- typedef pw::image<edge_values_t, pe_t> ima_t;
- mln_VAR(lg_ima, (edge_values | pe));
+ typedef pw::image<edge_values_t, pe_t> lg_ima_t;
+ lg_ima_t lg_ima = (edge_values | pe);
/*------.
| WST. |
@@ -161,8 +162,10 @@ int main()
// Perform a Watershed Transform.
int_u8 nbasins;
- mln_VAR(wshed, morpho::meyer_wst(lg_ima, nbh, nbasins));
- std::cout << "nbasins = " << nbasins << std::endl;
+ typedef pw::image<fun::i2v::array<int_u8>, p_edges<util::graph,
+ fun::i2v::array< util::site_pair<point2d> > > > wshed_t;
+ wshed_t wshed = morpho::meyer_wst(lg_ima, nbh, nbasins);
+ mln_assertion(nbasins == 5);
/*---------.
| Output. |
diff --git a/milena/tests/morpho/lena_line_graph_image_wst2.cc b/milena/tests/morpho/lena_line_graph_image_wst2.cc
index ba822fa..f704f90 100644
--- a/milena/tests/morpho/lena_line_graph_image_wst2.cc
+++ b/milena/tests/morpho/lena_line_graph_image_wst2.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -103,7 +104,9 @@ int main()
`----------------*/
// Line graph image.
- mln_VAR(lg_ima, morpho::line_gradient(input));
+ typedef pw::image<fun::i2v::array<input_val_t>, p_edges<util::graph,
+ fun::i2v::array< util::site_pair<point2d> > > > lg_ima_t;
+ lg_ima_t lg_ima = morpho::line_gradient(input);
/*-----------------.
| Simplification. |
@@ -112,7 +115,7 @@ int main()
typedef line_graph_elt_neighborhood<util::graph, lg_ima_t::pset::fun_t> nbh_t;
nbh_t nbh;
- mln_VAR(closed_lg_ima, morpho::closing_area_on_vertices(lg_ima, nbh, 20));
+ lg_ima_t closed_lg_ima = morpho::closing_area_on_vertices(lg_ima, nbh, 20);
/*------.
| WST. |
@@ -120,8 +123,10 @@ int main()
// Perform a Watershed Transform.
unsigned nbasins;
- mln_VAR(wshed, morpho::meyer_wst(closed_lg_ima, nbh, nbasins));
- std::cout << "nbasins = " << nbasins << std::endl;
+ typedef pw::image<fun::i2v::array<unsigned>, p_edges<util::graph,
+ fun::i2v::array< util::site_pair<point2d> > > > wshed_t;
+ wshed_t wshed = morpho::meyer_wst(closed_lg_ima, nbh, nbasins);
+ mln_assertion(nbasins == 46);
/*---------.
| Output. |
diff --git a/milena/tests/morpho/skeleton_constrained.cc b/milena/tests/morpho/skeleton_constrained.cc
index 5024f66..7ce78dc 100644
--- a/milena/tests/morpho/skeleton_constrained.cc
+++ b/milena/tests/morpho/skeleton_constrained.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -42,8 +43,6 @@
#include <mln/io/pbm/load.hh>
#include <mln/io/pbm/save.hh>
#include <mln/data/fill.hh>
-#include <mln/debug/println.hh>
-#include <mln/debug/println_with_border.hh>
#include <mln/pw/value.hh>
#include <mln/core/image/image_if.hh>
@@ -53,6 +52,8 @@
#include <mln/arith/revert.hh>
#include <mln/transform/distance_geodesic.hh>
+#include <mln/level/compare.hh>
+
#include "tests/data.hh"
@@ -65,8 +66,6 @@ namespace mln
{
extension::adjust_duplicate(ima, nbh);
- debug::println_with_border(ima);
-
image2d<unsigned> when_true(ima.domain()), when_false(ima.domain());
mln_piter(box2d) p(ima.domain());
for_all(p)
@@ -74,13 +73,34 @@ namespace mln
when_true(p) = connectivity_number_2d(ima, nbh.foreground(), p, true);
when_false(p) = connectivity_number_2d(ima, nbh.background(), p, false);
}
- debug::println("when true = ", when_true | pw::value(ima));
- debug::println("when false = ", when_false | pw::value(ima));
}
} // mln
+bool skl_ref_[22][18] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 } };
+
int main()
{
using namespace mln;
@@ -91,8 +111,9 @@ int main()
image2d<bool> pic;
io::pbm::load(pic, MLN_IMG_DIR "/tiny.pbm");
- mln_VAR( nbh,
- make::dual_neighb(pic, c4(), c8()) );
+ typedef neighb<win::multiple_size<2u, window<dpoint<grid::square, short int> >,
+ pw::value_<image2d<bool> > > > nbh_t;
+ nbh_t nbh = make::dual_neighb(pic, c4(), c8());
show_connectivity_numbers(pic, nbh);
@@ -104,14 +125,11 @@ int main()
image2d<int_u8> dmap = transform::distance_geodesic(logical::not_(pic),
nbh.foreground(),
mln_max(int_u8));
- debug::println("dst =", dmap | pw::value(pic));
dmap = arith::revert(dmap);
- mln_VAR( skl,
- morpho::skeleton_constrained(pic,
- nbh, is_simple_2d_t(),
- K, dmap) );
-
- debug::println("pic =", pic);
- debug::println("skl =", skl);
+ image2d<bool> skl = morpho::skeleton_constrained(pic,
+ nbh, is_simple_2d_t(),
+ K, dmap);
+ image2d<bool> skl_ref = make::image(skl_ref_);
+ mln_assertion(skl == skl_ref);
}
diff --git a/milena/tests/morpho/tree/compute_parent.cc b/milena/tests/morpho/tree/compute_parent.cc
index 6b4d34e..5707ed9 100644
--- a/milena/tests/morpho/tree/compute_parent.cc
+++ b/milena/tests/morpho/tree/compute_parent.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -31,16 +32,51 @@
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/var.hh>
#include <mln/core/image/image_if.hh>
#include <mln/core/site_set/p_array.hh>
#include <mln/level/sort_psites.hh>
+#include <mln/level/compare.hh>
#include <mln/pw/value.hh>
#include <mln/debug/println.hh>
#include <mln/morpho/tree/compute_parent.hh>
+static mln::image2d<mln::point2d> ref1()
+{
+ using namespace mln;
+
+ image2d<point2d> ref1(make::box2d(3,3));
+
+ ref1(point2d(0,0)) = point2d(0,0);
+ ref1(point2d(0,1)) = point2d(0,0);
+ ref1(point2d(0,2)) = point2d(0,0);
+ ref1(point2d(1,1)) = point2d(0,0);
+ ref1(point2d(2,2)) = point2d(2,2);
+
+ return ref1;
+}
+
+
+static mln::image2d<mln::point2d> ref2()
+{
+ using namespace mln;
+
+ image2d<point2d> ref2(make::box2d(3,3));
+
+ ref2(point2d(0,0)) = point2d(0,1);
+ ref2(point2d(0,1)) = point2d(0,2);
+ ref2(point2d(0,2)) = point2d(0,2);
+ ref2(point2d(1,0)) = point2d(0,0);
+ ref2(point2d(1,1)) = point2d(0,1);
+ ref2(point2d(1,2)) = point2d(0,1);
+ ref2(point2d(2,0)) = point2d(0,0);
+ ref2(point2d(2,1)) = point2d(0,0);
+ ref2(point2d(2,2)) = point2d(0,2);
+
+ return ref2;
+}
+
int main()
{
@@ -51,11 +87,12 @@ int main()
0, 1, 0,
0, 0, 1 };
image2d<bool> ima = make::image2d(vals);
- mln_VAR(sub, ima | pw::value(ima));
- debug::println(sub);
+ typedef image_if<image2d<bool>, pw::value_<image2d<bool> > > sub_t;
+ sub_t sub = ima | pw::value(ima);
- mln_VAR(par, morpho::tree::compute_parent(sub, c4(), sub.domain()));
- debug::println("par =", par);
+ typedef image_if<image2d<point2d>, pw::value_<image2d<bool> > > par_t;
+ par_t par = morpho::tree::compute_parent(sub, c4(), sub.domain());
+ mln_assertion(par == (ref1() | sub.domain()));
}
{
@@ -63,12 +100,11 @@ int main()
3, 2, 3,
3, 4, 1 };
image2d<unsigned char> ima = make::image2d(vals);
- debug::println(ima);
typedef p_array<point2d> S;
S s = level::sort_psites_increasing(ima);
- mln_VAR(par, morpho::tree::compute_parent(ima, c4(), s));
- debug::println("par =", par);
+ image2d<point2d> par = morpho::tree::compute_parent(ima, c4(), s);
+ mln_assertion(par == ref2());
}
}
diff --git a/milena/tests/pw/image.cc b/milena/tests/pw/image.cc
index a0f2ff9..1be36c1 100644
--- a/milena/tests/pw/image.cc
+++ b/milena/tests/pw/image.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
// (LRDE)
//
// This file is part of the Olena Library. This library is free
@@ -42,7 +42,9 @@ int main()
{
using namespace mln;
- mln_VAR(ima, fun::p2b::chess() | make::box2d(8, 8));
+ typedef pw::image<fun::p2b::chess,
+ box<mln::point<grid::square, short int> > > ima_t;
+ ima_t ima = fun::p2b::chess() | make::box2d(8, 8);
// trait::image::print(ima);
unsigned i = 0;
@@ -61,7 +63,8 @@ int main()
{
p_array<int> arr; // Sites are ints (why not?)
arr.insert(51); // Site 51.
- mln_VAR(ima, fun::i2v::array<int>(1) | arr); // An array psite converts to int so that works :-)
+ typedef pw::image<fun::i2v::array<int>, p_array<int> > ima_t;
+ ima_t ima = fun::i2v::array<int>(1) | arr; // An array psite converts to int so that works :-)
// trait::image::print(ima);
p_array<int>::psite p(ima.domain(), 0); // index 0 means the 1st element of arr
--
1.5.6.5
1
0