* complex.ixx, complex2.i: New.
* Makefile.am (meta_wrappers): Add complex.ixx.
(wrappers): Add complex2.i.
* python/Makefile.am (pyexec_LTLIBRARIES): Add _complex2.la.
(nodist__complex2_la_SOURCES, _complex2_la_LIBADD): New.
(CLEANFILES): Add $(nodist__complex2_la_SOURCES) complex2.py
complex2.py[co].
(nodist_python_PYTHON): Add complex2.py.
(complex_ixx_deps): New.
(complex2-wrap.cc): Add dependencies on
$(top_srcdir)/swilena/complex.ixx $(complex_ixx_deps).
(TESTS): Add complex2-misc.py.
* python/complex2-misc.py: New.
* python/swilena.py: Import the contents of module complex2.
---
swilena/ChangeLog | 19 +++
swilena/Makefile.am | 2 +
swilena/complex.ixx | 330 +++++++++++++++++++++++++++++++++++++++
swilena/complex2.i | 111 +++++++++++++
swilena/python/Makefile.am | 17 ++-
swilena/python/complex2-misc.py | 100 ++++++++++++
swilena/python/swilena.py | 2 +
7 files changed, 579 insertions(+), 2 deletions(-)
create mode 100644 swilena/complex.ixx
create mode 100644 swilena/complex2.i
create mode 100644 swilena/python/complex2-misc.py
diff --git a/swilena/ChangeLog b/swilena/ChangeLog
index 9790b3f..7f987ec 100644
--- a/swilena/ChangeLog
+++ b/swilena/ChangeLog
@@ -1,3 +1,22 @@
+2010-04-08 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Wrap a subset of complexes' features.
+
+ * complex.ixx, complex2.i: New.
+ * Makefile.am (meta_wrappers): Add complex.ixx.
+ (wrappers): Add complex2.i.
+ * python/Makefile.am (pyexec_LTLIBRARIES): Add _complex2.la.
+ (nodist__complex2_la_SOURCES, _complex2_la_LIBADD): New.
+ (CLEANFILES): Add $(nodist__complex2_la_SOURCES) complex2.py
+ complex2.py[co].
+ (nodist_python_PYTHON): Add complex2.py.
+ (complex_ixx_deps): New.
+ (complex2-wrap.cc): Add dependencies on
+ $(top_srcdir)/swilena/complex.ixx $(complex_ixx_deps).
+ (TESTS): Add complex2-misc.py.
+ * python/complex2-misc.py: New.
+ * python/swilena.py: Import the contents of module complex2.
+
2010-04-01 Roland Levillain <roland(a)lrde.epita.fr>
Wrap function mln::morpho::tree::max<I, N>.
diff --git a/swilena/Makefile.am b/swilena/Makefile.am
index 98eb4f6..be32ea6 100644
--- a/swilena/Makefile.am
+++ b/swilena/Makefile.am
@@ -23,6 +23,7 @@ meta_wrappers = \
box.ixx \
box_piter.ixx \
ch_value.ixx \
+ complex.ixx \
concat.ixx \
concrete.ixx \
coord.ixx \
@@ -41,6 +42,7 @@ meta_wrappers = \
wrappers = \
box2d.i \
box2d_piter.i \
+ complex2.i \
config.i \
dpoint2d.i \
image2d_int.i \
diff --git a/swilena/complex.ixx b/swilena/complex.ixx
new file mode 100644
index 0000000..ec5c196
--- /dev/null
+++ b/swilena/complex.ixx
@@ -0,0 +1,330 @@
+// -*- C++ -*-
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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 complex.ixx
+/// \brief A wrapper of mln::topo::complex<D>.
+
+%module complex
+
+%include "concat.ixx"
+%include "python-utils.ixx";
+
+%{
+#include "mln/topo/n_face.hh"
+#include "mln/topo/n_faces_set.hh"
+#include "mln/topo/algebraic_n_face.hh"
+#include "mln/topo/complex.hh"
+%}
+
+%include "mln/topo/complex.hh";
+
+
+/*-------------------------------.
+| Operators wrapping shortcuts. |
+`-------------------------------*/
+
+%define instantiate_boolean_binary_operator(Op, Name, T)
+%inline
+{
+ bool
+ Name (const T & f1, const T & f2) { return f1 Op f2; }
+}
+
+#if SWIGPYTHON
+%extend T
+{
+ bool
+ __ ## Name ## __ (const T & rhs) { return *$self Op rhs; }
+}
+#endif // !SWIGPYTHON
+%enddef // !instantiate_boolean_binary_operator
+
+
+/* It seems we cannot use %template nor %rename to wrap (non member)
+ template operators. Wrap them by hand using %inline. */
+
+%define instantiate_n_faces_set_binary_operator(Op, Name, N, D, LType, RType)
+%inline
+{
+ mln::topo::n_faces_set< N, D >
+ Name (const LType< N, D >& f1, const RType< N, D >& f2) { return f1
Op f2; }
+}
+
+#if SWIGPYTHON
+%extend LType< N, D >
+{
+ mln::topo::n_faces_set< N, D >
+ __ ## Name ## __ (const RType< N, D >& rhs) { return *$self Op rhs; }
+}
+#endif // !SWIGPYTHON
+%enddef // !instantiate_n_faces_set_binary_operator
+
+%define instantiate_n_faces_set_binary_operators(Op, Name, N, D)
+instantiate_n_faces_set_binary_operator(Op, Name, N, D,
+ mln::topo::algebraic_n_face,
+ mln::topo::algebraic_n_face)
+instantiate_n_faces_set_binary_operator(Op, Name, N, D,
+ mln::topo::algebraic_n_face,
+ mln::topo::n_face)
+instantiate_n_faces_set_binary_operator(Op, Name, N, D,
+ mln::topo::n_face,
+ mln::topo::algebraic_n_face)
+instantiate_n_faces_set_binary_operator(Op, Name, N, D,
+ mln::topo::n_face,
+ mln::topo::n_face)
+
+instantiate_n_faces_set_binary_operator(Op, Name, N, D,
+ mln::topo::n_faces_set,
+ mln::topo::algebraic_n_face)
+instantiate_n_faces_set_binary_operator(Op, Name, N, D,
+ mln::topo::n_faces_set,
+ mln::topo::n_face)
+%enddef // !instantiate_n_faces_set_binary_operators
+
+%define instantiate_algebraic_n_face_unary_operators(N, D)
+%inline
+{
+ mln::topo::algebraic_n_face< N, D >
+ neg (const mln::topo::n_face< N, D >& f) { return -f; }
+
+ mln::topo::algebraic_n_face< N, D >
+ neg (const mln::topo::algebraic_n_face< N, D >& f) { return -f; }
+}
+
+#if SWIGPYTHON
+%extend mln::topo::algebraic_n_face < N, D >
+{
+ mln::topo::algebraic_n_face< N, D > __neg__ () { return -*$self; }
+}
+
+%extend mln::topo::n_face < N, D >
+{
+ mln::topo::algebraic_n_face< N, D > __neg__ () { return -*$self; }
+}
+#endif // !SWIGPYTHON
+%enddef // !instantiate_algebraic_n_face_unary_operators
+
+
+/*-------.
+| Face. |
+`-------*/
+
+%include "mln/topo/face.hh";
+
+// Template members (conversions).
+%define instantiate_face_data_conversions(N, D)
+%extend mln::topo::face< D >
+{
+ // Construction from n_face<N, D>.
+ face< D > (const mln::topo::n_face<N, D>& f)
+ {
+ return new mln::topo::face< D >(f);
+ }
+
+ // Conversion to face_data<N>.
+ %template(data_ ## N) data< N >;
+}
+%enddef // !instantiate_face_data_conversions
+
+
+/*---------.
+| N-face. |
+`---------*/
+
+%include "mln/topo/n_face.hh";
+
+%define instantiate_n_face(N, D)
+ %ignore mln::topo::n_face<N, D>::lower_dim_adj_faces;
+ %ignore mln::topo::n_face<N, D>::higher_dim_adj_faces;
+ %template(n_face_ ## N ## _ ## D) mln::topo::n_face<N, D>;
+%enddef // !instantiate_n_face
+
+
+/*-----------------.
+| Algebraic face. |
+ `----------------*/
+
+%include "mln/topo/algebraic_face.hh";
+
+
+/*-------------------.
+| Algebraic n-face. |
+ `-------------------*/
+
+%include "mln/topo/algebraic_n_face.hh";
+
+%define instantiate_algebraic_n_face(N, D)
+ %ignore mln::topo::algebraic_n_face<N, D>::lower_dim_adj_faces;
+ %ignore mln::topo::algebraic_n_face<N, D>::higher_dim_adj_faces;
+ %template(algebraic_n_face_ ## N ## _ ## D) mln::topo::algebraic_n_face<N, D>;
+%enddef // !instantiate_algebraic_n_face
+
+
+/*--------------.
+| N-faces set. |
+`--------------*/
+
+%include "mln/topo/n_faces_set.hh";
+
+%define instantiate_n_faces_set(N, D)
+ %template(n_faces_set_ ## N ## _ ## D) mln::topo::n_faces_set<N, D>;
+%enddef // !instantiate_n_faces_set
+
+
+/*------------.
+| Face data. |
+`------------*/
+
+%include "mln/topo/face_data.hh";
+
+%define instantiate_face_data(N, D)
+ %template(face_data_ ## N ## _ ## D) mln::topo::face_data<N, D>;
+%enddef // !instantiate_face_data
+
+
+/*----------------.
+| Face Iterator. |
+`----------------*/
+
+%include "mln/core/concept/iterator.hh";
+%include "mln/topo/internal/complex_iterator_base.hh";
+%include "mln/topo/internal/complex_set_iterator_base.hh";
+%include "mln/topo/face_iter.hh";
+
+%{
+#include "mln/topo/face_iter.hh"
+%}
+
+// Generate base classes.
+%define instantiate_Iterator(ExactName, E)
+ %template(Iterator_ ## ExactName) mln::Iterator< E >;
+%enddef // !instantiate_Iterator
+
+%define instantiate_complex_iterator_base(ExactName, F, E)
+ instantiate_Iterator(ExactName, E)
+ %template(complex_iterator_base_ ## ExactName)
+ mln::topo::internal::complex_iterator_base< F, E >;
+%enddef // !instantiate_complex_iterator_base
+
+%define instantiate_complex_set_iterator_base(ExactName, F, E)
+ instantiate_complex_iterator_base(ExactName, F, E)
+ %template(complex_set_iterator_base_ ## ExactName)
+ mln::topo::internal::complex_set_iterator_base< F, E >;
+%enddef // !instantiate_complex_set_iterator_base
+
+// Generate mln::topo::face_fwd_iter< D >.
+%define instantiate_face_fwd_iter(Name, D)
+instantiate_complex_set_iterator_base(Name,
+ mln::topo::face< D >,
+ mln::topo::face_fwd_iter< D >)
+
+#if SWIGPYTHON
+// Handling iterators à la Python.
+%extend mln::topo::face_fwd_iter< D >
+{
+ mln::topo::face_fwd_iter< D >&
+ __iter__()
+ {
+ return *$self;
+ }
+}
+
+// Raise a Python `StopIteration' exception on `next()' if the
+// iterator is invalid.
+%exception mln::topo::face_fwd_iter< D >::next
+{
+ /* FIXME: Is it safe to use `arg1'? It seems to be pretty
+ low-level, and may not be part of Swig's standard interface. */
+ if (!arg1->is_valid())
+ {
+ PyErr_SetString(PyExc_StopIteration, "Invalid iterator");
+ return NULL;
+ }
+ $action
+}
+
+%extend mln::topo::face_fwd_iter< D >
+{
+ const mln::topo::face< D >
+ next()
+ {
+ // Keep a copy of the current site before incrementation.
+ const mln::topo::face< D > current = *$self;
+ // Delegate incrementation to `Super_Iterator's `next()' method.
+ $self->next();
+ return current;
+ }
+}
+#endif // !SWIGPYTHON
+
+%template(Name) mln::topo::face_fwd_iter< D >;
+%enddef // !instantiate_face_fwd_iter
+
+// Conversion helper for Python.
+#if SWIGPYTHON
+generate__str__(mln::topo::face_fwd_iter)
+#endif // !SWIGPYTHON
+
+
+/*----------.
+| Complex. |
+`----------*/
+
+// Generate an instantiation of mln::topo::complex<D>.
+%define instantiate_complex(Name, D)
+
+#if SWIGPYTHON
+// Conversion helper for Python.
+generate__str__(mln::topo::complex<D>)
+
+// Python iterator creation.
+%extend mln::topo::complex< D >
+{
+ mln::topo::face_fwd_iter< D >
+ __iter__() /* FIXME: No `const' here, to be compatible with
+ face_fwd_iter's ctor. This is bad. */
+ {
+ mln::topo::face_fwd_iter< D > f(*$self);
+ f.start();
+ return f;
+ }
+}
+#endif // !SWIGPYTHON
+
+%template(Name) mln::topo::complex<D>;
+%enddef // !instantiate_complex
+
+// Generate mln::topo::complex's template members.
+%define instantiate_complex_add_face(N, N_Plus_One, D)
+ %extend mln::topo::complex
+ {
+ mln::topo::n_face< N_Plus_One, D >
+ add_face(const mln::topo::n_faces_set< N, D >& adjacent_faces)
+ {
+ return $self->add_face(adjacent_faces);
+ }
+ };
+%enddef // !instantiate_complex_add_face
diff --git a/swilena/complex2.i b/swilena/complex2.i
new file mode 100644
index 0000000..95fa9bd
--- /dev/null
+++ b/swilena/complex2.i
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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 complex2.i
+/// \brief A wrapper of mln::topo::complex<2>.
+
+%module complex2
+
+%include "complex.ixx"
+
+instantiate_n_faces_set_binary_operators(+, add, 0, 2)
+instantiate_n_faces_set_binary_operators(+, add, 1, 2)
+
+instantiate_n_faces_set_binary_operators(-, sub, 0, 2)
+instantiate_n_faces_set_binary_operators(-, sub, 1, 2)
+
+instantiate_algebraic_n_face_unary_operators(0, 2)
+instantiate_algebraic_n_face_unary_operators(1, 2)
+
+
+/*-------.
+| Face. |
+`-------*/
+
+%template(face_2) mln::topo::face<2>;
+
+instantiate_face_data_conversions(0, 2)
+instantiate_face_data_conversions(1, 2)
+instantiate_face_data_conversions(2, 2)
+
+instantiate_boolean_binary_operator(==, eq, mln::topo::face<2>)
+
+// Conversion helper for Python.
+#if SWIGPYTHON
+generate__str__(mln::topo::face< 2 >)
+#endif // !SWIGPYTHON
+
+/*---------.
+| N-face. |
+`---------*/
+
+instantiate_n_face(0, 2)
+instantiate_n_face(1, 2)
+instantiate_n_face(2, 2)
+
+/*-----------------.
+| Algebraic face. |
+ `----------------*/
+
+%template(algebraic_face_2) mln::topo::algebraic_face<2>;
+
+/*-------------------.
+| Algebraic n-face. |
+ `-------------------*/
+
+instantiate_algebraic_n_face(0, 2)
+instantiate_algebraic_n_face(1, 2)
+instantiate_algebraic_n_face(2, 2)
+
+/*--------------.
+| N-faces set. |
+`--------------*/
+
+instantiate_n_faces_set(0, 2)
+instantiate_n_faces_set(1, 2)
+
+/*------------.
+| Face data. |
+`------------*/
+
+instantiate_face_data(0, 2)
+instantiate_face_data(1, 2)
+instantiate_face_data(2, 2)
+
+/*----------------.
+| Face iterator. |
+`----------------*/
+
+instantiate_face_fwd_iter(face_iter_2, 2)
+
+/*----------.
+| Complex. |
+`----------*/
+
+instantiate_complex_add_face(0, 1, 2)
+instantiate_complex_add_face(1, 2, 2)
+
+instantiate_complex(complex2, 2)
diff --git a/swilena/python/Makefile.am b/swilena/python/Makefile.am
index ea4b25d..3e5937d 100644
--- a/swilena/python/Makefile.am
+++ b/swilena/python/Makefile.am
@@ -74,6 +74,16 @@ CLEANFILES += $(nodist__config_la_SOURCES) config.py config.py[co]
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_config-wrap.Pcc@am__quote@
nodist_python_PYTHON += config.py
+## complex2.
+pyexec_LTLIBRARIES += _complex2.la
+nodist__complex2_la_SOURCES = complex2-wrap.cc
+_complex2_la_LIBADD = $(AM_LIBADD)
+CLEANFILES += $(nodist__complex2_la_SOURCES) complex2.py complex2.py[co]
+## Include the dependency files. Copied from Automake's generated
+## case for C++.
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_complex2-wrap.Pcc@am__quote@
+nodist_python_PYTHON += complex2.py
+
## point2d.
pyexec_LTLIBRARIES += _point2d.la
nodist__point2d_la_SOURCES = point2d-wrap.cc
@@ -231,6 +241,8 @@ rgb_ixx_deps = $(top_srcdir)/swilena/python-utils.ixx
box_ixx_deps = $(top_srcdir)/swilena/coord.ixx
+complex_ixx_deps = $(top_srcdir)/swilena/python-utils.ixx
+
morpho_ixx_deps = \
$(top_srcdir)/swilena/concrete.ixx \
$(top_srcdir)/swilena/ch_value.ixx
@@ -243,6 +255,8 @@ rgb8-wrap.cc: $(top_srcdir)/swilena/rgb.ixx $(rgb_ixx_deps)
box2d-wrap.cc: $(top_srcdir)/swilena/box.ixx $(box_ixx_deps)
box2d_piter-wrap.cc: $(top_srcdir)/swilena/box_piter.ixx
+complex2-wrap.cc: $(top_srcdir)/swilena/complex.ixx $(complex_ixx_deps)
+
point2d-wrap.cc: $(top_srcdir)/swilena/concat.ixx
point2d-wrap.cc: $(top_srcdir)/swilena/python-utils.ixx
@@ -316,7 +330,6 @@ CLEANFILES += $(bin_SCRIPTS) $(noinst_SCRIPTS)
include $(top_srcdir)/swilena/run.mk
-## FIXME: Do we really need to pass top_srcdir and top_builddir to run?
TESTS_ENVIRONMENT = \
top_srcdir="$(top_srcdir)" top_builddir="$(top_builddir)" $(RUN)
# Ensure `run' is rebuilt before the tests are run.
@@ -338,7 +351,7 @@ $(srcdir)/run.stamp: $(RUN_IN)
# extension as argument. We could improve this by adding options such
# as `--python' to `run'.
TESTS = \
- box2d-misc.py \
+ box2d-misc.py complex2-misc.py \
image2d-misc.py morpho-fun.py morpho-segm.py max-tree.py \
dynamic-image2d-misc.py
diff --git a/swilena/python/complex2-misc.py b/swilena/python/complex2-misc.py
new file mode 100644
index 0000000..87fb27a
--- /dev/null
+++ b/swilena/python/complex2-misc.py
@@ -0,0 +1,100 @@
+#! /usr/bin/env python
+# -*- coding: latin-1 -*-
+
+# Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+#
+# This file is part of Olena.
+#
+# Olena is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, version 2 of the License.
+#
+# Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+
+# \file python/mesh-complex-segm.py
+# \brief Test complex2.
+#
+# See also Milena's tests/topo/complex.cc.
+
+import data
+from swilena import *
+
+# A 2-d (simplicial) complex and its adjacency graph.
+#
+# v0 e3 v3
+# o-----------o v0----e3----v3
+# / \ ,-----. / / \ | /
+# / . \ \ t1/ / / \ t1 /
+# e0 / / \ e1\ / / e4 e0. ,e1Ž `e4
+# / /t0 \ \ ' / / t0 \ /
+# / `-----' \ / / | \ /
+# o-----------o v1----e2----v2
+# v1 e2 v2
+#
+# v = vertex (0-face)
+# e = edge (1-face)
+# t = triangle (2-face)
+
+## ---------------------- ##
+## Complex construction. ##
+## ---------------------- ##
+
+c = complex2()
+
+# 0-faces (points).
+v0 = c.add_face()
+v1 = c.add_face()
+v2 = c.add_face()
+v3 = c.add_face()
+
+# 1-faces (segments).
+e0 = c.add_face(-v1 + v0)
+e1 = c.add_face(-v0 + v2)
+e2 = c.add_face(-v2 + v1)
+e3 = c.add_face(-v0 + v3)
+e4 = c.add_face(-v3 + v2)
+
+# 2-faces (triangles).
+t0 = c.add_face( e0 + e1 + e2)
+t1 = c.add_face(-e1 + e3 + e4)
+
+print c
+
+
+## ------------------ ##
+## Handles and data. ##
+## ------------------ ##
+
+# Get the face data from (``static'') face handle E0.
+face1 = e0.data()
+
+# Face handle.
+f = face_2(e0)
+print f
+print
+
+# Get the face data from (``dynamic'') face handle AF.
+face2 = f.data_1()
+
+
+## ----------- ##
+## Iteration. ##
+## ----------- ##
+
+# --------------- #
+# Iterator on C. #
+# --------------- #
+
+# (Forward) Iterator on a complex (not complex_image), or more
+# precisely on (all) the faces of complex C.
+for f in c:
+ print f
+
+
+# FIXME: Test more iterators.
diff --git a/swilena/python/swilena.py b/swilena/python/swilena.py
index 6c4dc89..6538046 100644
--- a/swilena/python/swilena.py
+++ b/swilena/python/swilena.py
@@ -24,6 +24,8 @@ import ltihooks
import config
+from complex2 import *
+
from box2d import *
from point2d import *
from dpoint2d import *
--
1.5.6.5