From 2e88ea7eef3364429a75a2ede4bc1b9814534b10 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sat, 24 Jan 2026 12:35:42 +0100 Subject: [PATCH 1/2] [graphics] corrected bug when displaying tubes with polygonal simplification --- src/graphics/figures/codac2_Figure2D.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 45b725c5a..d9c638a88 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -460,7 +460,7 @@ void draw_tube_common(Figure2D& fig, const SlicedTube& x, int ma else { - int group_size = std::max(1, (int)(1.*n/max_nb_slices_to_display)); + int group_size = std::max(1, (int)((1.*n)/max_nb_slices_to_display)); for(auto it = x.tdomain()->rbegin() ; it != x.tdomain()->rend(); ) { @@ -468,13 +468,12 @@ void draw_tube_common(Figure2D& fig, const SlicedTube& x, int ma ConvexPolygon p(x.slice(it)->codomain()); it++; - for(int j = 0; j < group_size-1 && it != x.tdomain()->rend(); j++,it++) + int j; + for(j = 0; j < group_size-1 && it != x.tdomain()->rend(); j++,it++) p |= ConvexPolygon(x.slice(it)->codomain()); fig.draw_polygon(p, c); - if(it != x.tdomain()->rend()) - { - it--; it--; - } + if(j != 0) + it--; } } } From 3760b59a40fcc8bc8a5840bdeb8c4306a5722348 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sat, 24 Jan 2026 12:36:11 +0100 Subject: [PATCH 2/2] [doc/manual] moving IntervalVector code to src.* files --- .../manual/intervals/IntervalVector_class.rst | 185 ++++++------------ doc/manual/manual/intervals/src.cpp | 73 +++++++ doc/manual/manual/intervals/src.py | 75 +++++++ 3 files changed, 209 insertions(+), 124 deletions(-) diff --git a/doc/manual/manual/intervals/IntervalVector_class.rst b/doc/manual/manual/intervals/IntervalVector_class.rst index 2f441c74a..2f889a922 100644 --- a/doc/manual/manual/intervals/IntervalVector_class.rst +++ b/doc/manual/manual/intervals/IntervalVector_class.rst @@ -25,42 +25,21 @@ A box can be created from: .. tabs:: - .. group-tab:: Python + .. group-tab:: Python - .. code-block:: py + .. literalinclude:: src.py + :language: py + :start-after: [intervalvector-class-1-beg] + :end-before: [intervalvector-class-1-end] + :dedent: 4 - # Default box: [-oo,oo]^n - x = IntervalVector(3) + .. group-tab:: C++ - # Cube [-1,3]^2 - y = IntervalVector(2, Interval(-1,3)) - - # From a list of bounds (each entry is [lb,ub]) - z = IntervalVector([[3,4],[4,6]]) # [3,4]×[4,6] - - # From a list of components (Intervals and/or bounds pairs) - q = IntervalVector([y[1], z[0], [0,oo]]) # [-1,3]×[3,4]×[0,oo] - - # From a point (degenerate intervals) - p = Vector([0.42,0.42,0.42]) - bp = IntervalVector(p) # [0.42,0.42]^3 - - .. group-tab:: C++ - - .. code-block:: c++ - - // Default box: [-oo,oo]^n (Interval default constructor) - IntervalVector x(3); - - // Cube [-1,3]^2 - IntervalVector y(2, Interval(-1,3)); - - // From a list of bounds (initializer-list style) - IntervalVector z{{3,4},{4,6}}; // [3,4]×[4,6] - - // From a point (degenerate intervals) - Vector p({0.42,0.42,0.42}); - IntervalVector bp(p); // [0.42,0.42]^3 + .. literalinclude:: src.cpp + :language: c++ + :start-after: [intervalvector-class-1-beg] + :end-before: [intervalvector-class-1-end] + :dedent: 4 .. note:: @@ -74,45 +53,22 @@ Components are intervals; indexing is 0-based in Python/C++ and 1-based in Matla .. tabs:: - .. group-tab:: Python - - .. code-block:: py - - x = IntervalVector(2, [-1,3]) # [-1,3]^2 - x[1] = Interval(0,10) # [-1,3]×[0,10] - - # Iterating/accessing over components - y = IntervalVector(2) - for i, xi in enumerate(x): - y[i] = xi - - # Unpacking (Python convenience) - a,b = x - assert a == x[0] and b == x[1] - - # Building a new box from existing components - v = IntervalVector([*x, [3,6]]) # concatenation in Python - # v == [[-1,3]×[0,10]×[3,6]] - - # Resize: new components are default-initialized ([-oo,oo]) - v.resize(4) # v == [[-1,3]×[0,10]×[3,6]×[-oo,oo]] - s = v.subvector(1,2) # [0,10]×[3,6] + .. group-tab:: Python - .. group-tab:: C++ + .. literalinclude:: src.py + :language: py + :start-after: [intervalvector-class-2-beg] + :end-before: [intervalvector-class-2-end] + :dedent: 4 - .. code-block:: c++ + .. group-tab:: C++ - IntervalVector x(2, Interval(-1,3)); // [-1,3]^2 - x[1] = Interval(0, 10); // [-1,3]×[0,10] + .. literalinclude:: src.cpp + :language: c++ + :start-after: [intervalvector-class-2-beg] + :end-before: [intervalvector-class-2-end] + :dedent: 4 - // Accessing components - const Interval& x0 = x[0]; - - // Resize: new components are default-initialized ([-oo,oo]) - x.resize(4); // x == [-1,3]×[0,10]×[-oo,oo]×[-oo,oo] - - // Subvector / segment extraction - IntervalVector s = x.subvector(1,2); // [0,10]×[-oo,oo] Box properties -------------- @@ -127,30 +83,21 @@ Typical accessors you will use in practice: .. tabs:: - .. group-tab:: Python - - .. code-block:: py - - x = IntervalVector([[0,2],[-1,3]]) + .. group-tab:: Python - n = x.size() # dimension - # Common box information (component-wise): - lo = x.lb() # Vector of lower bounds - hi = x.ub() # Vector of upper bounds - m = x.mid() # Vector of midpoints - d = x.diam() # Vector of diameters + .. literalinclude:: src.py + :language: py + :start-after: [intervalvector-class-3-beg] + :end-before: [intervalvector-class-3-end] + :dedent: 4 - .. group-tab:: C++ + .. group-tab:: C++ - .. code-block:: c++ - - IntervalVector x{{0,2},{-1,3}}; - - Index n = x.size(); - Vector lo = x.lb(); - Vector hi = x.ub(); - Vector m = x.mid(); - Vector d = x.diam(); + .. literalinclude:: src.cpp + :language: c++ + :start-after: [intervalvector-class-3-beg] + :end-before: [intervalvector-class-3-end] + :dedent: 4 .. note:: @@ -171,25 +118,21 @@ Common predicates include: .. tabs:: - .. group-tab:: Python - - .. code-block:: py - - x = IntervalVector([[0,1],[2,3]]) - y = IntervalVector([[0.5,2],[1,4]]) + .. group-tab:: Python - assert x.intersects(y) - assert x.is_subset(y) + .. literalinclude:: src.py + :language: py + :start-after: [intervalvector-class-4-beg] + :end-before: [intervalvector-class-4-end] + :dedent: 4 - .. group-tab:: C++ + .. group-tab:: C++ - .. code-block:: c++ - - IntervalVector x{{0,1},{2,3}}; - IntervalVector y{{0.5,2},{1,4}}; - - assert(x.intersects(y)); - assert(x.is_subset(y)); + .. literalinclude:: src.cpp + :language: c++ + :start-after: [intervalvector-class-4-beg] + :end-before: [intervalvector-class-4-end] + :dedent: 4 Advanced operations ------------------- @@ -220,29 +163,23 @@ Because ``IntervalVector`` is a vector of ``Interval``, standard arithmetic is n * interactions with real vectors/matrices, * matrix–vector products involving :class:`~codac.IntervalMatrix`. -.. tabs:: - - .. group-tab:: Python - - .. code-block:: py - - x = IntervalVector([[0,1],[2,3]]) - y = IntervalVector([[1,2],[0,1]]) - - z1 = x+y - z2 = 2*x - z3 = x-1 + .. tabs:: - .. group-tab:: C++ + .. group-tab:: Python - .. code-block:: c++ + .. literalinclude:: src.py + :language: py + :start-after: [intervalvector-class-5-beg] + :end-before: [intervalvector-class-5-end] + :dedent: 4 - IntervalVector x{{0,1},{2,3}}; - IntervalVector y{{1,2},{0,1}}; + .. group-tab:: C++ - IntervalVector z1 = x+y; - IntervalVector z2 = 2.*x; - IntervalVector z3 = x-1.; + .. literalinclude:: src.cpp + :language: c++ + :start-after: [intervalvector-class-5-beg] + :end-before: [intervalvector-class-5-end] + :dedent: 4 .. admonition:: Technical documentation diff --git a/doc/manual/manual/intervals/src.cpp b/doc/manual/manual/intervals/src.cpp index 35bf55fab..cf43b4fb0 100644 --- a/doc/manual/manual/intervals/src.cpp +++ b/doc/manual/manual/intervals/src.cpp @@ -108,4 +108,77 @@ TEST_CASE("Interval class - manual") CHECK(Approx(x) == 0.9999999999999999); CHECK(x != 1.); } +} + +TEST_CASE("IntervalVector class - manual") +{ + { + // [intervalvector-class-1-beg] + // Default box: [-oo,oo]^n (Interval default constructor) + IntervalVector x(3); + + // Cube [-1,3]^2 + IntervalVector y = IntervalVector::constant(2,{-1,3}); + + // From a list of bounds (initializer-list style) + IntervalVector z{{3,4},{4,6}}; // [3,4]×[4,6] + + // From a point (degenerate intervals) + Vector p({0.42,0.42,0.42}); + IntervalVector bp(p); // [0.42,0.42]^3 + // [intervalvector-class-1-end] + } + + { + // [intervalvector-class-2-beg] + IntervalVector x = IntervalVector::constant(2,{-1,3}); // [-1,3]^2 + x[1] = Interval(0,10); // [-1,3]×[0,10] + + // Accessing components + const Interval& x0 = x[0]; + + // Resize: new components are default-initialized ([-oo,oo]) + x.resize(4); // x == [-1,3]×[0,10]×[-oo,oo]×[-oo,oo] + + // Subvector / segment extraction + IntervalVector s = x.subvector(1,2); // [0,10]×[-oo,oo] + // [intervalvector-class-2-end] + + (void)x0; // avoid warning on unused variable + } + + { + // [intervalvector-class-3-beg] + IntervalVector x{{0,2},{-1,3}}; + + Index n = x.size(); + Vector lo = x.lb(); + Vector hi = x.ub(); + Vector m = x.mid(); + Vector d = x.diam(); + // [intervalvector-class-3-end] + + (void)n; // avoid warning on unused variable + } + + { + // [intervalvector-class-4-beg] + IntervalVector x{{0,1},{2,3}}; + IntervalVector y{{-0.5,2},{1,4}}; + + assert(x.intersects(y)); + assert(x.is_subset(y)); + // [intervalvector-class-4-end] + } + + { + // [intervalvector-class-5-beg] + IntervalVector x{{0,1},{2,3}}; + IntervalVector y{{1,2},{0,1}}; + + IntervalVector z1 = x+y; + IntervalVector z2 = 2.*x; + IntervalVector z3 = x/2.; + // [intervalvector-class-5-end] + } } \ No newline at end of file diff --git a/doc/manual/manual/intervals/src.py b/doc/manual/manual/intervals/src.py index a5b7869a8..633fde7be 100644 --- a/doc/manual/manual/intervals/src.py +++ b/doc/manual/manual/intervals/src.py @@ -83,5 +83,80 @@ def tests_Interval_manual(test): # [interval-class-7-end] test.assertTrue(Approx(x) == 0.9999999999999999 and x != 1) + + def tests_IntervalVector_manual(test): + + # [intervalvector-class-1-beg] + # Default box: [-oo,oo]^n + x = IntervalVector(3) + + # Cube [-1,3]^2 + y = IntervalVector.constant(2,[-1,3]) + + # From a list of bounds (each entry is [lb,ub]) + z = IntervalVector([[3,4],[4,6]]) # [3,4]×[4,6] + + # From a list of components (Intervals and/or bounds pairs) + q = IntervalVector([y[1], z[0], [0,oo]]) # [-1,3]×[3,4]×[0,oo] + + # From a point (degenerate intervals) + p = Vector([0.42,0.42,0.42]) + bp = IntervalVector(p) # [0.42,0.42]^3 + # [intervalvector-class-1-end] + + + # [intervalvector-class-2-beg] + x = IntervalVector.constant(2,[-1,3]) # [-1,3]^2 + x[1] = Interval(0,10) # [-1,3]×[0,10] + + # Iterating/accessing over components + y = IntervalVector(2) + for i, xi in enumerate(x): + y[i] = xi + + # Unpacking (Python convenience) + a,b = x + assert a == x[0] and b == x[1] + + # Building a new box from existing components + v = IntervalVector([*x, [3,6]]) # concatenation in Python + # v == [[-1,3]×[0,10]×[3,6]] + + # Resize: new components are default-initialized ([-oo,oo]) + v.resize(4) # v == [[-1,3]×[0,10]×[3,6]×[-oo,oo]] + s = v.subvector(1,2) # [0,10]×[3,6] + # [intervalvector-class-2-end] + + + # [intervalvector-class-3-beg] + x = IntervalVector([[0,2],[-1,3]]) + + n = x.size() # dimension + # Common box information (component-wise): + lo = x.lb() # Vector of lower bounds + hi = x.ub() # Vector of upper bounds + m = x.mid() # Vector of midpoints + d = x.diam() # Vector of diameters + # [intervalvector-class-3-end] + + + # [intervalvector-class-4-beg] + x = IntervalVector([[0,1],[2,3]]) + y = IntervalVector([[-0.5,2],[1,4]]) + + assert x.intersects(y) + assert x.is_subset(y) + # [intervalvector-class-4-end] + + + # [intervalvector-class-5-beg] + x = IntervalVector([[0,1],[2,3]]) + y = IntervalVector([[1,2],[0,1]]) + + z1 = x+y + z2 = 2*x + z3 = x/2 + # [intervalvector-class-5-end] + if __name__ == '__main__': unittest.main() \ No newline at end of file