diff --git a/.gitignore b/.gitignore index c35bf0562..64523ced0 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,10 @@ wheelhouse/ # Graphics files examples/**/*.xml +examples/**/*.bmp +examples/**/*.png +examples/**/*.jpg +examples/**/*.svg *.ipe # Matlab files diff --git a/doc/manual/manual/extensions/capd/capd.rst b/doc/manual/manual/extensions/capd/capd.rst index 40c23731e..590fe4c98 100644 --- a/doc/manual/manual/extensions/capd/capd.rst +++ b/doc/manual/manual/extensions/capd/capd.rst @@ -11,6 +11,7 @@ To use CAPD with Codac, you first need to install the CAPD library. You can find Note that as CAPD is a C++ only library, the content present in this page is **only available in C++**. +.. _subsec-extensions-capd-capd-install: Installing the ``codac-capd`` extension --------------------------------------- diff --git a/doc/manual/manual/extensions/capd/peibos_capd.rst b/doc/manual/manual/extensions/capd/peibos_capd.rst index fb80ca017..3fae692b3 100644 --- a/doc/manual/manual/extensions/capd/peibos_capd.rst +++ b/doc/manual/manual/extensions/capd/peibos_capd.rst @@ -31,7 +31,7 @@ The PEIBOS function takes at least six arguments : - The final time for the integration of the ODE. - A timestep to get intermediate states. - The inverse chart for the gnomonic atlas (an analytic function). -- The list of symmetries for the gnomonic atlas. Note that each symmetry is represented as a hyperoctahedral symmetry, see :ref:`sec-actions-octasym`. +- The list of symmetries for the gnomonic atlas. Note that each symmetry is represented as a hyperoctahedral symmetry, see :ref:`sec-tools-octasym`. - A resolution :math:`\epsilon`. The initial box :math:`\left[-1,1\right]^m` will initiallly be splitted in boxes with a diameter smaller than :math:`\epsilon`. - Eventually an offset vector can be specified if the initial set is not centered around the origin. - Eventually a flag can be set to True to get the verbose. diff --git a/doc/manual/manual/functions/peibos/peibos.rst b/doc/manual/manual/functions/peibos/peibos.rst index f2afcf83f..aaa1bcdd0 100644 --- a/doc/manual/manual/functions/peibos/peibos.rst +++ b/doc/manual/manual/functions/peibos/peibos.rst @@ -13,6 +13,7 @@ Let us consider an initial set :math:`\mathbb{X}_0 \subset \mathbb{R}^n` with it Considering a function :math:`\mathbf{f}:\mathbb{R}^n \to \mathbb{R}^p`, :math:`n \leq p`, the PEIBOS tool allows to compute the set :math:`\mathbf{Y}=\left\{ \mathbf{f}(\mathbf{x}) \mid \mathbf{x} \in \partial \mathbb{X}_0 \right\}`. .. _subsec-functions-peibos-gnomonic-atals: + Gnomonic atlas -------------- @@ -60,7 +61,7 @@ The PEIBOS function takes at least four arguments : - The studied analytic function. - The inverse chart for the gnomonic atlas (an analytic function). -- The list of symmetries for the gnomonic atlas. Note that each symmetry is represented as a hyperoctahedral symmetry, see :ref:`sec-actions-octasym`. +- The list of symmetries for the gnomonic atlas. Note that each symmetry is represented as a hyperoctahedral symmetry, see :ref:`sec-tools-octasym`. - A resolution :math:`\epsilon`. The initial box :math:`\left[-1,1\right]^m` will initiallly be splitted in boxes with a diameter smaller than :math:`\epsilon`. - Eventually an offset vector can be specified if the initial set is not centered around the origin. - Eventually a flag can be set to True to get the verbose. diff --git a/doc/manual/manual/visualization/2d_example.rst b/doc/manual/manual/visualization/2d_example.rst new file mode 100644 index 000000000..688af0c50 --- /dev/null +++ b/doc/manual/manual/visualization/2d_example.rst @@ -0,0 +1,10 @@ +.. _sec-graphics-2d-example: + +2D graphical example +==================== + +Below is an example covering a wide variety of drawing functions, colors, styles etc. + +* `Python version `_ +* `C++ version `_ +* `Matlab version `_ diff --git a/doc/manual/manual/visualization/3d_example.rst b/doc/manual/manual/visualization/3d_example.rst new file mode 100644 index 000000000..7df5e6dfc --- /dev/null +++ b/doc/manual/manual/visualization/3d_example.rst @@ -0,0 +1,11 @@ +.. _sec-graphics-3d-example: + +3D graphical example +==================== + +Below is an example covering a wide variety of drawing functions, colors, styles etc. + +* `Python version `_ +* `C++ version `_ +* `Matlab version `_ + diff --git a/doc/manual/manual/visualization/3d_visualization.rst b/doc/manual/manual/visualization/3d_visualization.rst index bfe22788b..8c2ee2766 100644 --- a/doc/manual/manual/visualization/3d_visualization.rst +++ b/doc/manual/manual/visualization/3d_visualization.rst @@ -36,86 +36,139 @@ Drawing functions Below are the detailled available drawing functions. The shapes that can be drawn are: Geometric shapes - - Triangle - - Parallelogram - - Star-shaped polygon - Box - - Parallelepiped - - Zonotope + - Sphere - Arrow + - Zonotope + - Parallelepiped + - Parallelogram + - Triangle + - Star-shaped polygon - Parametric surface - - Sphere + +Vehicles + - Car + - Plane Paving - PavingOut (Paving with contractors) - PavingInOut (Paving with separators) - Subpaving -Vehicles - - Car - - Plane - -In addition, a function ``draw_axes`` is available to draw the three axes of the 3D space. -.. doxygenfunction:: codac2::Figure3D::draw_axes(double) - :project: codac Note that only the stroke color is used in all of the supported drawing functions. +In addition, a function ``draw_axes`` is available to draw the three axes of the 3D space. It can take two arguments : + +- float : the size of the axes +- Vector : the origin of the axes + + Geometric shapes ---------------- -.. doxygenfunction:: codac2::Figure3D::draw_triangle(const Vector&, const Matrix&, const Vector&, const Vector&, const Vector&, const StyleProperties&) - :project: codac +All the drawable geometric objects can take a last optionnal argument to set up their stroke color. +For further details, refer to :ref:`subsec-graphics-colors-style-properties`. -.. doxygenfunction:: codac2::Figure3D::draw_triangle(const Vector&, const Vector&, const Vector&, const StyleProperties&) - :project: codac +The geometric shapes that can be drawn and their arguments are listed below : + +- draw_box + + - IntervalVector : the box to draw + +- draw_sphere + + - Vector : the center of the sphere + - Matrix : the scaling matrix + +- draw_arrow + + - Vector : start of the arrow + - Matrix : orientation of the arrow (first column) + +- draw_zonotope + + - Zonotope: the zonotope to draw + +- draw_parallelepiped + + - Parallelepiped : the parallelepiped to draw + +- draw_parallelogram (defined by :math:`c + A (p + [-1,1]*v1 + [-1,1]*v2)`) + + - Vector : c, the translation + - Matrix : A, the scaling + - Vector : p, base point + - Vector : v1, first generator + - Vector : v2, second generator + +- draw_triangle + + - Vector : first point + - Vector : second point + - Vector : third point + +- draw_triangle + + - Vector : translation applied to the triangle + - Matrix : scaling matrix applied to the triangle + - Vector : first point + - Vector : second point + - Vector : third point The ``draw_polygon`` can be used to draw a `star-shaped polygon `_ when the vectors are coplanar, and more generally a sequence of adjacent triangles sharing a same vertex. -.. doxygenfunction:: codac2::Figure3D::draw_polygon(const Vector&, const Matrix&, const std::vector&, const StyleProperties&) - :project: codac +- draw_polygon -.. doxygenfunction:: codac2::Figure3D::draw_box(const IntervalVector&, const StyleProperties&) - :project: codac + - Vector : translation applied to the polygon + - Matrix : scaling matrix applied to the polygon + - vector : vector where each element is a point of the polygon to draw -.. doxygenfunction:: codac2::Figure3D::draw_parallelogram(const Vector&, const Matrix&, const Vector&, const Vector&, const Vector&, const StyleProperties&) - :project: codac +- draw_surface -.. doxygenfunction:: codac2::Figure3D::draw_parallelepiped(const Parallelepiped&, const StyleProperties&) - :project: codac + - Vector : the translation applied to the surface + - Matrix : scaling applied to the surface + - Interval : bounds of p1 + - double : incrementation for p1 + - Interval : bounds of p2 + - double : incrementation for p2 + - function -\> Vector : the function of the surface, linking each (p1,p2) to a 3D point -.. doxygenfunction:: codac2::Figure3D::draw_zonotope(const Zonotope&, const StyleProperties&) - :project: codac +Vehicles +-------- -.. doxygenfunction:: codac2::Figure3D::draw_arrow(const Vector&, const Matrix& A, const StyleProperties&) - :project: codac +All the drawable vehicles can take a last optionnal argument to set up their stroke color. +For further details, refer to :ref:`subsec-graphics-colors-style-properties`. -.. doxygenfunction:: codac2::Figure3D::draw_surface(const Vector&, const Matrix&, const Interval&, double, const Interval&, double, std::function, const StyleProperties&) - :project: codac +The vehicles that can be drawn and their arguments are listed below : -.. doxygenfunction:: codac2::Figure3D::draw_sphere(const Vector&, const Matrix&, const StyleProperties&) - :project: codac +- draw_car + + - Vector : center of the car + - Matrix : orientation of the car + +- draw_plane + + - Vector : center of the plane + - Matrix : orientation of the plane + - bool : (optionnal) defines if the yaw axis is up, default to true Paving ------ -.. doxygenfunction:: codac2::Figure3D::draw_paving(const PavingOut& p, const StyleProperties&) - :project: codac +When a paving is drawn, only the inside and boundary boxes are drawn. This is done to avoid outside boxes masking them. -.. doxygenfunction:: codac2::Figure3D::draw_paving(const PavingInOut& p, const StyleProperties&, const StyleProperties&) - :project: codac +If only one type of paving is drawn (for example a paving with contractors), only one :ref:`subsec-graphics-colors-style-properties` can be defined to choose its edge color. +If two types are drawn (boundary and inside), two :ref:`subsec-graphics-colors-style-properties` can be passed to select both colors. -.. doxygenfunction:: codac2::Figure3D::draw_subpaving(const Subpaving

&, const StyleProperties&) - :project: codac +The paving that can be drawn and their arguments are listed below : -Vehicles --------- +- draw_paving -.. doxygenfunction:: codac2::Figure3D::draw_car(const Vector&, const Matrix&, const StyleProperties&) - :project: codac + - PavingOut | PavingInOut : the paving to draw -.. doxygenfunction:: codac2::Figure3D::draw_plane(const Vector&, const Matrix&, bool, const StyleProperties&) - :project: codac +- draw_subpaving + - Subpaving : the subpaving to draw \ No newline at end of file diff --git a/doc/manual/manual/visualization/colors.rst b/doc/manual/manual/visualization/colors.rst index 4a44c86c7..aaba29598 100644 --- a/doc/manual/manual/visualization/colors.rst +++ b/doc/manual/manual/visualization/colors.rst @@ -128,7 +128,7 @@ Additionnal methods are available for any useful purpose: fig.draw_box(IntervalVector({{2.6,3.1},{2.6,3.1}}),StyleProperties({Color({108,90,78},Model().HSV),Color({108,90,78,20},Model().HSV)})); - +.. _subsec-graphics-colors-style-properties: StyleProperties --------------- @@ -208,6 +208,48 @@ For more information, see :ref:`subsec-graphics-colors-optional-arguments`. fig.draw_box(IntervalVector({{2,5},{2,5}}), StyleProperties(Color().red(), "..", "layer1", "w:0.1", "z:1.5")); % Red edge, dotted line, line width of 0.1, z-value of 1.5 and on layer1 +.. _subsec-graphics-colors-paving-style: +Paving style +------------ + +To change the color used to draw a paving, the ``draw_paving`` functions can take an optional argument which is the ``PavingStyle``. +Predefined styles are + +- blue_green (default_style) +- blue_white +- blue_pink +- black_white + +A custom ``PavingStyle`` can also be created from three ``StyleProperties`` : the boundary, the outside and the inside. +Below is an example of the different possibilities. + +.. tabs:: + + .. code-tab:: py + + DefaultFigure.draw_paving(p) # default style, blue_green + DefaultFigure.draw_paving(p,PavingStyle.blue_pink()) #blue_pink style + # orange boundary, purple outside and blue inside + paving_style = PavingStyle([Color.dark_orange(),Color.orange()],[Color.dark_purple(),Color.purple()],[Color.dark_blue(),Color.blue()]) + DefaultFigure.draw_paving(p,paving_style) + + + + .. code-tab:: c++ + + DefaultFigure::draw_paving(p); + DefaultFigure::draw_paving(p,PavingStyle::blue_pink()); + // orange boundary, purple outside and blue inside + PavingStyle paving_style ({Color::dark_orange(),Color::orange()},{Color::dark_purple(),Color::purple()},{Color::dark_blue(),Color::blue()}); + DefaultFigure::draw_paving(p,paving_style); + + .. code-tab:: matlab + + DefaultFigure().draw_paving(p); + DefaultFigure().draw_paving(p,PavingStyle().blue_pink()); + % orange boundary, purple outside and blue inside + paving_style = PavingStyle(StyleProperties({Color().dark_orange(),Color().orange()}),StyleProperties({Color().dark_purple(),Color().purple()}),StyleProperties({Color().dark_blue(),Color().blue()})); + DefaultFigure().draw_paving(p,paving_style); Color maps ---------- @@ -299,6 +341,7 @@ You can also create your own color map : Note that you can add RGB and HSV colors to the same color map. The model of the color map will define the interpolation space. +.. _subsec-graphics-colors-style-gradient-properties: StyleGradientProperties ----------------------- diff --git a/doc/manual/manual/visualization/figures.rst b/doc/manual/manual/visualization/figures.rst index f146017eb..95a525a95 100644 --- a/doc/manual/manual/visualization/figures.rst +++ b/doc/manual/manual/visualization/figures.rst @@ -156,4 +156,5 @@ VIBes only Some methods are exclusive to the real-time display with VIBes : - center_viewbox : takes two Vector as arguments, the center and radius of each axis -- auto_scale : takes no argument, the figure will be automatically scaled to fit the window \ No newline at end of file +- auto_scale : takes no argument, the figure will be automatically scaled to fit the window +- save : takes the name of the file as argument and saves the current state of the VIBes window to the file. Allowed formats are png, jpg, bmp and svg. \ No newline at end of file diff --git a/doc/manual/manual/visualization/functions.rst b/doc/manual/manual/visualization/functions.rst index b3efcc917..93ff22e54 100644 --- a/doc/manual/manual/visualization/functions.rst +++ b/doc/manual/manual/visualization/functions.rst @@ -101,115 +101,175 @@ Paving Geometric shapes ---------------- -.. doxygenfunction:: codac2::Figure2D::draw_point(const Vector&, const StyleProperties&) - :project: codac +All the drawable geometric objects can take a last optionnal argument to set up their stroke color, fill color, line style etc. +For further details, refer to :ref:`subsec-graphics-colors-style-properties`. -.. doxygenfunction:: codac2::Figure2D::draw_box(const IntervalVector&, const StyleProperties&) - :project: codac +The geometric shapes that can be drawn and their arguments are listed below : -.. doxygenfunction:: codac2::Figure2D::draw_circle(const Vector&, double, const StyleProperties&) - :project: codac +- draw_point -.. doxygenfunction:: codac2::Figure2D::draw_ring(const Vector&, const Interval&, const StyleProperties&) - :project: codac + - Vector : 2D coordinate of the point to draw -.. doxygenfunction:: codac2::Figure2D::draw_line(const Vector&, const Vector&, const StyleProperties&) - :project: codac +- draw_box -.. doxygenfunction:: codac2::Figure2D::draw_line(const Segment&, const StyleProperties&) - :project: codac + - IntervalVector : the 2D box to draw -.. doxygenfunction:: codac2::Figure2D::draw_arrow(const Vector&, const Vector&, float, const StyleProperties&) - :project: codac +- draw_circle -.. doxygenfunction:: codac2::Figure2D::draw_polyline(const std::vector&, const StyleProperties&) - :project: codac + - Vector : the center of the circle + - double : the radius of the circle + +- draw_ring -.. doxygenfunction:: codac2::Figure2D::draw_polyline(const std::vector&, float, const StyleProperties&) - :project: codac + - Vector : the center of the ring + - Interval : the ring range : inner and outer radius -.. doxygenfunction:: codac2::Figure2D::draw_polygon(const Polygon&, const StyleProperties&) - :project: codac +- draw_pie -.. doxygenfunction:: codac2::Figure2D::draw_parallelepiped(const Parallelepiped&, const StyleProperties&) - :project: codac + - Vector : the center of the pie + - Interval : the pie range : inner and outer radius + - Interval : the pie angle : begin and end angle (in radian) -.. doxygenfunction:: codac2::Figure2D::draw_zonotope(const Zonotope&, const StyleProperties&) - :project: codac +- draw_line -.. doxygenfunction:: codac2::Figure2D::draw_pie(const Vector&, const Interval&, const Interval&, const StyleProperties&) - :project: codac + - Vector : the first point of the line + - vector : the second point of the line -.. doxygenfunction:: codac2::Figure2D::draw_ellipse(const Vector&, const Vector&, double, const StyleProperties&) - :project: codac +- draw_line -.. doxygenfunction:: codac2::Figure2D::draw_ellipsoid(const Ellipsoid&, const StyleProperties&) - :project: codac + - Segment : the segment to draw + +- draw_arrow + + - Vector : the first point of the line + - vector : the second point of the line + - float : the length of the tip of the arrow + +- draw_polyline + + - vector : vector where each element is a point of the polyline to draw + +- draw_polyline + + - vector : vector where each element is a point of the polyline to draw + - float : the length of the tip of the arrow + +- draw_polygone + + - Polygon : the polygon to draw + +- draw_parallelepiped + + - Parallelepiped : the parallelepiped to draw + +- draw_zonotope + + - Zonotope : the zonotope to draw + +- draw_ellipse + + - Vector : center of the ellipse + - Vector : Half-lengths of the ellipse + - double : rotation angle of the ellipse (in radian) + +- draw_ellipsoid + + - Ellipsoid : the ellipsoid to draw Trajectories and tubes ---------------------- -.. doxygenfunction:: codac2::Figure2D::draw_trajectory(const SampledTraj&, const StyleProperties&) - :project: codac -.. doxygenfunction:: codac2::Figure2D::draw_trajectory(const AnalyticTraj&, const StyleProperties&) - :project: codac +All the drawable trajectories and tubes can take a last optionnal argument to set up their stroke color, fill color, line style etc. +For further details, refer to :ref:`subsec-graphics-colors-style-properties` for constant fill and edge color, +and :ref:`subsec-graphics-colors-style-gradient-properties` for the use of a colormap. + +The trajectories and tubes that can be drawn are listed below: + +- plot_trajectory + + - SampledTraj | AnalyticTraj : the 1D trajectory to draw (x-axis is the time) -Trajectories can be drawn with a ColorMap instead of the classic StyleProperties. This can be done by passing a ColorMap object as the second argument. +- plot_trajectories -.. doxygenfunction:: codac2::Figure2D::draw_trajectory(const SampledTraj&, const StyleGradientProperties&) - :project: codac + - SampledTraj | AnalyticTraj : the nD trajectory to draw component by component (x-axis is the time) -.. doxygenfunction:: codac2::Figure2D::draw_trajectory(const AnalyticTraj&, const StyleGradientProperties&) - :project: codac +- plot_tube -.. doxygenfunction:: codac2::Figure2D::draw_tube(const SlicedTube&, const StyleProperties&, int) - :project: codac + - SlicedTube : the 1D tube to draw (x-axis is the time) -.. doxygenfunction:: codac2::Figure2D::draw_tube(const SlicedTube&, const StyleGradientProperties&, int) - :project: codac +- plot_tube -.. doxygenfunction:: codac2::Figure2D::plot_tube(const SlicedTube&, const StyleProperties&) - :project: codac + - SlicedTube : the 1D tube to draw (x-axis is the time) + - SlicedTube : the derivative of the tube to draw -.. doxygenfunction:: codac2::Figure2D::plot_tube(const SlicedTube&, const SlicedTube&, const StyleProperties&) - :project: codac +- draw_trajectory + + - SampledTraj | AnalyticTraj : the 2D trajectory to draw + +- draw_tube + + - SlicedTube : the 2D tube to draw Vehicles -------- -.. doxygenfunction:: codac2::Figure2D::draw_tank(const Vector&, float, const StyleProperties&) - :project: codac +All the drawable vehicles can take a last optionnal argument to set up their stroke color, fill color, line style etc. +For further details, refer to :ref:`subsec-graphics-colors-style-properties`. -.. doxygenfunction:: codac2::Figure2D::draw_AUV(const Vector&, float, const StyleProperties&) - :project: codac +The vehicles that can be drawn and their arguments are listed below : -.. doxygenfunction:: codac2::Figure2D::draw_motor_boat(const Vector&, float, const StyleProperties&) - :project: codac +- draw_tank -Miscellaneous -------------- + - Vector : the 3D state of the tank to draw (x,y,theta in radian) + - float : the size of the tank -.. doxygenfunction:: codac2::Figure2D::draw_text(const std::string&, const Vector&, double, const StyleProperties&) - :project: codac +- draw_AUV -.. doxygenfunction:: codac2::Figure2D::draw_raster(const std::string&, const IntervalVector&, const StyleProperties&) - :project: codac + - Vector : the 3D state of the AUV to draw (x,y,theta in radian) + - float : the size of the AUV + +- draw_motor_boat + + - Vector : the 3D state of the motor boat to draw (x,y,theta in radian) + - float : the size of the motor boat Paving ------ -.. doxygenfunction:: codac2::Figure2D::draw_paving(const PavingOut&, const PavingStyle&) - :project: codac +All the drawable pavings can take a last optionnal argument to set up their style for the inside, boundary and outside boxes. +For further details, refer to :ref:`subsec-graphics-colors-paving-style`. + +The paving that can be drawn and their arguments are listed below : + +- draw_paving + + - PavingOut | PavingInOut : the paving to draw + +- draw_paving + + - PavingOut | PavingInOut : the paving to draw + - function(Figure2D,IntervalVector,StyleProperties) : Custom drawing function (for instance, if one wants to draw in polar coordinates) + +- draw_subpaving + + - Subpaving : the subpaving to draw + +Miscellaneous +------------- + +Other objects can be drawn and can take a last optionnal argument to set up their stroke color, fill color, line style etc. +For further details, refer to :ref:`subsec-graphics-colors-style-properties`. + +These objects are : -.. doxygenfunction:: codac2::Figure2D::draw_paving(const PavingOut&, const std::function&, const PavingStyle&) - :project: codac +- draw_text -.. doxygenfunction:: codac2::Figure2D::draw_paving(const PavingInOut&, const PavingStyle&) - :project: codac + - string : the text to draw + - Vector : the 2D Vector for the position of the top-left corner of the text + - float : the scale of the text (VIBes only) -.. doxygenfunction:: codac2::Figure2D::draw_paving(const PavingInOut&, const std::function&, const PavingStyle&) - :project: codac +- draw_raster -.. doxygenfunction:: codac2::Figure2D::draw_subpaving(const Subpaving

&, const StyleProperties&) - :project: codac + - string : The name of the file (the path is relative to the VIBes' server folder) + - IntervalVector : The bounding box of the raster diff --git a/doc/manual/manual/visualization/index.rst b/doc/manual/manual/visualization/index.rst index b129f8f69..042b77f2c 100644 --- a/doc/manual/manual/visualization/index.rst +++ b/doc/manual/manual/visualization/index.rst @@ -11,4 +11,6 @@ Visualization colors.rst vibes.rst ipe.rst - 3d_visualization.rst \ No newline at end of file + 2d_example.rst + 3d_visualization.rst + 3d_example.rst \ No newline at end of file diff --git a/examples/00_graphics/graphic_animation.cpp b/examples/00_graphics/graphic_animation.cpp index 1b567d086..6f357e68c 100644 --- a/examples/00_graphics/graphic_animation.cpp +++ b/examples/00_graphics/graphic_animation.cpp @@ -21,4 +21,25 @@ int main() theta += 2.0 * M_PI / (double) steps; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } + + Figure2D fig_save ("Animation with exports",GraphicOutput::VIBES|GraphicOutput::IPE); + fig_save.set_window_properties({600,50},{500,500}); // position, window size + fig_save.set_axes(axis(0,{-0.5,4}), axis(1,{-0.5,1.5})); + + Vector X({0,0,0}); + + ColorMap cmap = ColorMap::rainbow(); + for (double t = 0; t < 2.*PI; t+=PI/20.) + { + fig_save.draw_tank(X, 0.05, cmap.color(t/(2.*PI))); + X+=Vector({0.1*cos(X[2]),0.1*sin(X[2]),0.1*cos(t)}); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (Interval(PI).inflate(0.1).contains(t)) + { + fig_save.save("animation_tank.png"); + fig_save.save("animation_tank.jpg"); + fig_save.save("animation_tank.bmp"); + fig_save.save("animation_tank.svg"); + } + } } \ No newline at end of file diff --git a/examples/00_graphics/graphic_animation.py b/examples/00_graphics/graphic_animation.py index 69955e528..24dfff9e7 100644 --- a/examples/00_graphics/graphic_animation.py +++ b/examples/00_graphics/graphic_animation.py @@ -1,4 +1,5 @@ from codac import * +import math import time fig = Figure2D("Animation", GraphicOutput.VIBES | GraphicOutput.IPE) @@ -11,4 +12,23 @@ fig.clear() fig.draw_point([5*cos(theta).mid(), 5*sin(theta).mid()], Color.red()) theta += 2*PI / steps - time.sleep(0.1) \ No newline at end of file + time.sleep(0.1) + +fig_save = Figure2D("Animation with exports", GraphicOutput.VIBES | GraphicOutput.IPE) +fig_save.set_window_properties([600,50],[500,500]) # position, window size +fig_save.set_axes(axis(0,[-0.5,4]), axis(1,[-0.5,1.5])) + +X = Vector([0,0,0]) +t = 0 +cmap = ColorMap.rainbow() + +while t <2*PI: + fig_save.draw_tank(X, 0.05, cmap.color(t/(2*PI))) + X+=Vector([0.1*math.cos(X[2]),0.1*math.sin(X[2]),0.1*math.cos(t)]) + time.sleep(0.1) + if (Interval(PI).inflate(0.1).contains(t)): + fig_save.save("animation_tank.png") + fig_save.save("animation_tank.jpg") + fig_save.save("animation_tank.bmp") + fig_save.save("animation_tank.svg") + t += PI/20 \ No newline at end of file diff --git a/examples/06_graphics_3D/main.cpp b/examples/06_graphics_3D/main.cpp index a77f85495..d0fcf103f 100644 --- a/examples/06_graphics_3D/main.cpp +++ b/examples/06_graphics_3D/main.cpp @@ -48,9 +48,9 @@ int main() { Color::yellow(0.6), "sphere" }); fig_examples.draw_arrow({0,2,0},{{-1,0,0},{0,1,1},{0,0,-1}}, Color::red(1.0)); - fig_examples.draw_car({-1,0,0},0.3*Matrix::Identity(3,3), + fig_examples.draw_car({-1,0,0},0.3*Matrix::eye(3,3), { Color::green(0.8), "car" }); - fig_examples.draw_plane({3,0,0},0.5*Matrix::Identity(3,3),true, + fig_examples.draw_plane({3,0,0},0.5*Matrix::eye(3,3),true, { Color::dark_gray(0.8), "plane" }); @@ -69,7 +69,7 @@ int main() {{1,0,0},{0,0.5,0},{0,0.2,0.1}}}, { Color::blue(0.5), "parallelepiped" }); - fig_examples.draw_surface({0,-2,0}, 0.5*Matrix::Identity(3,3), Interval(0,2*PI), + fig_examples.draw_surface({0,-2,0}, 0.5*Matrix::eye(3,3), Interval(0,2*PI), 0.05*PI, Interval(0,2*PI), 0.05*PI, [](double phi,double psi) -> Vector { return {(1-cos(phi))*sin(phi), diff --git a/examples/06_graphics_3D/main.m b/examples/06_graphics_3D/main.m new file mode 100644 index 000000000..e0429cff8 --- /dev/null +++ b/examples/06_graphics_3D/main.m @@ -0,0 +1,57 @@ +import py.codac4matlab.* + +x = VectorVar(3); +f = AnalyticFunction({x},vec(-sqr(x(3))+2*x(3)*sin(x(3)*x(1))+cos(x(3)*x(2)),2*x(3)*cos(x(3)*x(1))-sin(x(3)*x(2)))); + +ctc = CtcInverse(f,IntervalVector().zero(2)); +p_ctc = pave(IntervalVector({{0,2},{2,4},{0,10}}), ctc, 0.02); +fig_ctc = Figure3D("Paving contractor"); +fig_ctc.draw_paving(p_ctc); + +sep_ellipsoid1 = SepInverse (AnalyticFunction({x},0.5*sqr(x(1))+x(1)*x(2)+x(1)*x(3)+2*sqr(x(2))+2*sqr(x(3))),Interval(0.4,1)); +sep_ellipsoid2 = SepInverse (AnalyticFunction({x},3*sqr(x(1))+x(1)*x(2)+x(1)*x(3)+sqr(x(2))+sqr(x(3))),Interval(0.,1)); +p_sep = pave(IntervalVector({{-1.5,1.5},{-1.5,1.5},{-1.5,1.5}}), sep_ellipsoid1.inter(sep_ellipsoid2), 0.1); +fig_sep = Figure3D("Paving separator"); +fig_sep.draw_axes(0.4); +fig_sep.draw_paving(p_sep); + +eye_3d = Matrix({{1,0,0},{0,1,0},{0,0,1}}); + +fig_examples = Figure3D("3D examples"); +fig_examples.draw_axes(); +fig_examples.draw_axes(0.5); +fig_examples.draw_axes(2.0,Vector([0.5,0.5,0.5])); +fig_examples.draw_triangle(Vector([1,0,0]),Vector([0,1,0]),Vector([0,0,1]),StyleProperties(Color().dark_green(0.5),"triangle")) +fig_examples.draw_triangle(Vector([2,0,0]),Matrix({{-1,0,0},{0,1,1},{0,0,-1}}), Vector([1.,0.,0.]),Vector([0.,1.,0.]),Vector([0.,0.,1.]),StyleProperties(Color().purple(0.5))); +fig_examples.draw_sphere(Vector([0,0,2]),Matrix({{-1,0,0},{0,1,1},{0,0,-1}}), StyleProperties(Color().yellow(0.6),"sphere")); +fig_examples.draw_arrow(Vector([0,2,0]),Matrix({{-1,0,0},{0,1,1},{0,0,-1}}),StyleProperties(Color().red(1.0))); +fig_examples.draw_car(Vector([-1,0,0]),0.3*eye_3d, StyleProperties(Color().green(0.8),"car")); +fig_examples.draw_plane(Vector([3,0,0]),0.5*eye_3d,true,StyleProperties(Color().dark_gray(0.8),"plane")); + +fig_examples.draw_zonotope(Zonotope(Vector([1.5,1.5,1.5]), ... + Matrix({{0.3,-0.2,-0.2,0.3,-0.1,0.0},{0.2,0.1,-0.1,0.0,0.05,0.2},{0.4,0.3,0.0,-0.1,0.2,0.1}})),StyleProperties(Color().dark_green(1.0),"zonotope")); +fig_examples.draw_zonotope(Zonotope(Vector([-1.5,-1.5,-1.5]), ... + Matrix({{0.3,-0.2,-0.2,0.3,-0.2,-0.1,0.0,0.0}, ... + {0.2,0.1,-0.1,0.0,0.0,0.05,0.2,0.0}, ... + {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.1}})), ... + StyleProperties(Color().dark_green(1.0),"zonotope2")); + +code = sprintf([ ... + 'import math\n' ... + 'from codac4matlab import Vector\n' ... + 'f = lambda phi, psi: Vector([\n' ... + ' (1-math.cos(phi))*math.sin(phi),\n' ... + ' (1-math.cos(2*phi))*math.cos(phi)*math.cos(psi),\n' ... + ' (1-math.cos(phi))*math.cos(phi)*math.sin(psi)\n' ... + '])']); + +f = pyrun(code, "f"); + +fig_examples.draw_surface( ... + Vector([0, -2, 0]), ... + 0.5 * eye_3d, ... + Interval(0, 2*pi), 0.05*pi, ... + Interval(0, 2*pi), 0.05*pi, ... + f, ... + StyleProperties(Color().red(0.6), "example_surface") ... +); \ No newline at end of file diff --git a/examples/06_graphics_3D/main.py b/examples/06_graphics_3D/main.py index 4ebf27354..a92d701bd 100644 --- a/examples/06_graphics_3D/main.py +++ b/examples/06_graphics_3D/main.py @@ -27,7 +27,7 @@ fig_examples.draw_axes(2.0,[0.5,0.5,0.5]) fig_examples.draw_triangle([1,0,0],[0,1,0],[0,0,1],StyleProperties(Color.dark_green(0.5),"triangle")) fig_examples.draw_triangle([2,0,0], - Matrix([[2,0,0],[-1,0,0],[0,1,1]]), + Matrix([[-1,0,0],[0,1,1],[0,0,-1]]), [1,0,0],[0,1,0],[0,0,1],Color.purple(0.5)) fig_examples.draw_sphere([0,0,2],Matrix([[-1,0,0],[0,1,1],[0,0,-1]]), StyleProperties(Color.yellow(0.6),"sphere")) diff --git a/examples/custom_sep/custom_sep.py b/examples/custom_sep/custom_sep.py index 850c4969d..4bb71a10c 100644 --- a/examples/custom_sep/custom_sep.py +++ b/examples/custom_sep/custom_sep.py @@ -10,7 +10,7 @@ def __init__(self, S_): def separate(self, x): inner,outer = self.S.separate(x) # separates x into two boxes - return [outer,inner] # inner/outer boxes are permuted + return BoxPair(inner,outer) # inner/outer boxes are permuted # Trying this custom separator diff --git a/python/src/core/separators/codac2_py_Sep.cpp b/python/src/core/separators/codac2_py_Sep.cpp index b3dcde5ee..ca3ca25be 100644 --- a/python/src/core/separators/codac2_py_Sep.cpp +++ b/python/src/core/separators/codac2_py_Sep.cpp @@ -82,21 +82,49 @@ py::class_ export_Sep(py::module& m) py::return_value_policy::reference_internal, py::keep_alive<1,0>()) + ; + // Intersection of separators + if constexpr(!FOR_MATLAB) + { + py_sep + .def("__and__", [](const SepBase& s1, const SepBase& s2) + { + return SepInter(s1.copy(),s2.copy()); + }, + SEPINTER_OPERATORINTER_CONST_S1_REF_CONST_S2_REF) + + .def("__and__", [](const SepBase& s1, const IntervalVector& x2) + { + auto s2 = SepWrapper(x2); + return SepInter(s1.copy(),s2.copy()); + }, + SEPINTER_OPERATORINTER_CONST_INTERVALVECTOR_REF_CONST_S2_REF) + + ; + } + + if constexpr(FOR_MATLAB) + { + py_sep + .def("inter", [](const SepBase& s1, const SepBase& s2) + { + return SepInter(s1.copy(),s2.copy()); + }, + SEPINTER_OPERATORINTER_CONST_S1_REF_CONST_S2_REF) + + .def("inter", [](const SepBase& s1, const IntervalVector& x2) + { + auto s2 = SepWrapper(x2); + return SepInter(s1.copy(),s2.copy()); + }, + SEPINTER_OPERATORINTER_CONST_INTERVALVECTOR_REF_CONST_S2_REF) + + ; + } - .def("__and__", [](const SepBase& s1, const SepBase& s2) - { - return SepInter(s1.copy(),s2.copy()); - }, - SEPINTER_OPERATORINTER_CONST_S1_REF_CONST_S2_REF) - - .def("__and__", [](const SepBase& s1, const IntervalVector& x2) - { - auto s2 = SepWrapper(x2); - return SepInter(s1.copy(),s2.copy()); - }, - SEPINTER_OPERATORINTER_CONST_INTERVALVECTOR_REF_CONST_S2_REF) + py_sep .def("__rand__", [](const SepBase& s1, const IntervalVector& x2) { auto s2 = SepWrapper(x2); diff --git a/python/src/core/separators/codac2_py_SepInter.cpp b/python/src/core/separators/codac2_py_SepInter.cpp index 4d2d2382d..6747ba9c7 100644 --- a/python/src/core/separators/codac2_py_SepInter.cpp +++ b/python/src/core/separators/codac2_py_SepInter.cpp @@ -58,11 +58,30 @@ void export_SepInter(py::module& m, py::class_& pysep) BOXPAIR_SEPINTER_SEPARATE_CONST_INTERVALVECTOR_REF_CONST, "x"_a) - .def("__iand__", [](SepInter& s1, const SepBase& s2) - { - s1 &= s2.copy(); - return s1; - }, - SEPINTER_REF_SEPINTER_OPERATORINTEREQ_CONST_S_REF) - ; + ; + + if constexpr(!FOR_MATLAB) + { + exported + + .def("__iand__", [](SepInter& s1, const SepBase& s2) + { + s1 &= s2.copy(); + return s1; + }, + SEPINTER_REF_SEPINTER_OPERATORINTEREQ_CONST_S_REF) + ; + } + + if constexpr(FOR_MATLAB) + { + exported + .def("self_inter", [](SepInter& s1, const SepBase& s2) + { + s1 &= s2.copy(); + return s1; + }, + SEPINTER_REF_SEPINTER_OPERATORINTEREQ_CONST_S_REF) + ; + } } \ No newline at end of file diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index 41b26324c..e78d90819 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -109,6 +109,10 @@ void export_Figure2D(py::module& m) .def("clear", &Figure2D::clear, VOID_FIGURE2D_CLEAR) + + .def("save", &Figure2D::save, + VOID_FIGURE2D_SAVE_CONST_STRING_REF, + "filename"_a) .def("scaled_unit", &Figure2D::scaled_unit, DOUBLE_FIGURE2D_SCALED_UNIT_CONST) diff --git a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp index 38c465bbf..3b5da24b3 100644 --- a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp +++ b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp @@ -16,7 +16,7 @@ using namespace std; using namespace codac2; Figure2D_IPE::Figure2D_IPE(const Figure2D& fig) - : OutputFigure2D(fig), _f(fig.name() + ".xml"), + : OutputFigure2D(fig), _x_offset(0.03*_fig.axes()[0].limits.diam()), _y_offset(0.03*_fig.axes()[1].limits.diam()) { @@ -25,23 +25,7 @@ Figure2D_IPE::Figure2D_IPE(const Figure2D& fig) Figure2D_IPE::~Figure2D_IPE() { - draw_axes(); - print_header_page(); - _f.close(); - - _f = std::ofstream(_fig.name() + ".xml", std::ofstream::binary | std::ofstream::app); - std::ifstream f_temp_content(_fig.name() + "_tmp.xml", std::ofstream::binary); - - for (const auto& item : _items) - _f << item.second; - - f_temp_content.close(); - std::remove((_fig.name() + "_tmp.xml").c_str()); - _f.close(); - - _f = std::ofstream(_fig.name() + ".xml", std::ofstream::app); - _f << "\n\n"; - _f.close(); + save(_fig.name()+"."); } void Figure2D_IPE::init_figure() @@ -172,6 +156,8 @@ void Figure2D_IPE::update_axes() _ipe_grid_size/(_fig.axes()[0].limits.diam()+_x_offset), _ipe_grid_size/(_fig.axes()[1].limits.diam()+_y_offset) }; + + draw_axes(); } void Figure2D_IPE::update_window_properties() @@ -190,10 +176,26 @@ void Figure2D_IPE::clear() // clear _color map and layers _colors.clear(); _layers.clear(); + _items.clear(); init_figure(); } +void Figure2D_IPE::save(const std::string& filename) +{ + std::size_t dot_position = filename.find_last_of('.'); + std::string file_name = filename.substr(0, dot_position); + _f = std::ofstream(file_name + ".xml", std::ofstream::binary | std::ofstream::app); + + print_header_page(); + + for (const auto& item : _items) + _f << item.second; + + _f << "\n\n"; + _f.close(); +} + std::string ipe_str(const Color& c) { return c.hex_str().substr(1); diff --git a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h index 23d0e15f6..ddfeba394 100644 --- a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h +++ b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h @@ -72,6 +72,13 @@ namespace codac2 */ void clear(); + /** + * \brief Saves the figure to a file + * + * \param filename Name of the file to save the figure to + */ + void save(const std::string& filename); + /** * \brief Begins a new path in the IPE file * diff --git a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp index eb3e40059..aeb59a32b 100644 --- a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp +++ b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp @@ -93,6 +93,11 @@ void Figure2D_VIBes::clear() _layers.clear(); } +void Figure2D_VIBes::save(const std::string& filename) +{ + vibes::saveImage(filename, _fig.name()); +} + void Figure2D_VIBes::draw_point(const Vector& c, const StyleProperties& style) { assert(_fig.size() <= c.size()); diff --git a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.h b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.h index 04572df9c..f780f544a 100644 --- a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.h +++ b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.h @@ -65,6 +65,13 @@ namespace codac2 * \brief Clears the figure */ void clear(); + + /** + * \brief Saves the figure to a file + * + * \param filename Name of the file to save the figure to + */ + void save(const std::string& filename); // Geometric shapes diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 15c9503c8..2658e715b 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -111,6 +111,12 @@ void Figure2D::clear() output_fig->clear(); } +void Figure2D::save(const std::string& filename) +{ + for(const auto& output_fig : _output_figures) + output_fig->save(filename); +} + double Figure2D::scaled_unit() const { return std::max(_axes[0].limits.diam(),_axes[1].limits.diam()) / _window_size.max_coeff(); diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index 3b920c734..ec637baa8 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -182,6 +182,13 @@ namespace codac2 */ void clear(); + /** + * \brief Saves the figure to a file + * + * \param filename Name of the file to save the figure to + */ + void save(const std::string& filename); + /** * \brief Getter for the scaling factor of the figure * @@ -715,6 +722,17 @@ namespace codac2 selected_fig()->clear(); } + /** + * \brief Saves the figure to a file + * + * \param filename Name of the file to save the figure to + */ + static void save(const std::string& filename) + { + auto_init(); + selected_fig()->save(filename); + } + // Geometric shapes /** diff --git a/src/graphics/figures/codac2_OutputFigure2D.h b/src/graphics/figures/codac2_OutputFigure2D.h index a83ba57e4..a4157949c 100644 --- a/src/graphics/figures/codac2_OutputFigure2D.h +++ b/src/graphics/figures/codac2_OutputFigure2D.h @@ -73,6 +73,13 @@ namespace codac2 * \brief Clears the figure */ virtual void clear() = 0; + + /** + * \brief Saves the figure to a file + * + * \param filename Name of the file to save the figure to + */ + virtual void save(const std::string& filename) = 0; protected: