@@ -470,6 +470,33 @@ bool plot(const std::vector<Numeric> &x, const std::vector<Numeric> &y, const st
470470 return res;
471471}
472472
473+ // FIXME: <https://stackoverflow.com/questions/76077363/why-does-matplotlib-cpp-throw-runtime-exceptions-in-the-3d-examples>
474+ // Given a figure, create a subplot with a 3d axis and return a pointer to that axis. also calls incref on the axis pointer.
475+ PyObject* init_3d_axis (PyObject *fig)
476+ {
477+ PyObject *asp_kwargs = PyDict_New ();
478+ PyDict_SetItemString (asp_kwargs, " projection" , PyString_FromString (" 3d" ));
479+
480+ PyObject *asp = PyObject_GetAttrString (fig, " add_subplot" );
481+ Py_INCREF (asp);
482+ PyObject *tmpax = PyObject_Call (asp, detail::_interpreter::get ().s_python_empty_tuple , asp_kwargs);
483+ Py_INCREF (tmpax);
484+
485+ PyObject *gca = PyObject_GetAttrString (fig, " gca" );
486+ if (!gca) throw std::runtime_error (" No gca" );
487+ Py_INCREF (gca);
488+ PyObject *axis = PyObject_Call (gca, detail::_interpreter::get ().s_python_empty_tuple , detail::_interpreter::get ().s_python_empty_tuple );
489+
490+ if (!axis) throw std::runtime_error (" No axis" );
491+ Py_INCREF (axis);
492+
493+ Py_DECREF (gca);
494+ Py_DECREF (tmpax);
495+ Py_DECREF (asp);
496+ return axis;
497+ }
498+
499+
473500// TODO - it should be possible to make this work by implementing
474501// a non-numpy alternative for `detail::get_2darray()`.
475502#ifndef WITHOUT_NUMPY
@@ -555,6 +582,8 @@ void plot_surface(const std::vector<::std::vector<Numeric>> &x,
555582 Py_DECREF (fig_exists);
556583 if (!fig) throw std::runtime_error (" Call to figure() failed." );
557584
585+ PyObject *axis = init_3d_axis (fig);
586+ /*
558587 PyObject *gca_kwargs = PyDict_New();
559588 PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
560589
@@ -569,6 +598,7 @@ void plot_surface(const std::vector<::std::vector<Numeric>> &x,
569598
570599 Py_DECREF(gca);
571600 Py_DECREF(gca_kwargs);
601+ */
572602
573603 PyObject *plot_surface = PyObject_GetAttrString (axis, " plot_surface" );
574604 if (!plot_surface) throw std::runtime_error (" No surface" );
@@ -723,6 +753,8 @@ void plot3(const std::vector<Numeric> &x,
723753 }
724754 if (!fig) throw std::runtime_error (" Call to figure() failed." );
725755
756+ PyObject *axis = init_3d_axis (fig);
757+ /*
726758 PyObject *gca_kwargs = PyDict_New();
727759 PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
728760
@@ -737,6 +769,7 @@ void plot3(const std::vector<Numeric> &x,
737769
738770 Py_DECREF(gca);
739771 Py_DECREF(gca_kwargs);
772+ */
740773
741774 PyObject *plot3 = PyObject_GetAttrString (axis, " plot" );
742775 if (!plot3) throw std::runtime_error (" No 3D line plot" );
@@ -1126,6 +1159,8 @@ bool scatter(const std::vector<NumericX>& x,
11261159 Py_DECREF (fig_exists);
11271160 if (!fig) throw std::runtime_error (" Call to figure() failed." );
11281161
1162+ PyObject *axis = init_3d_axis (fig);
1163+ /*
11291164 PyObject *gca_kwargs = PyDict_New();
11301165 PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
11311166
@@ -1140,6 +1175,7 @@ bool scatter(const std::vector<NumericX>& x,
11401175
11411176 Py_DECREF(gca);
11421177 Py_DECREF(gca_kwargs);
1178+ */
11431179
11441180 PyObject *plot3 = PyObject_GetAttrString (axis, " scatter" );
11451181 if (!plot3) throw std::runtime_error (" No 3D line plot" );
@@ -1503,6 +1539,8 @@ bool quiver(const std::vector<NumericX>& x, const std::vector<NumericY>& y, cons
15031539 detail::_interpreter::get ().s_python_empty_tuple );
15041540 if (!fig) throw std::runtime_error (" Call to figure() failed." );
15051541
1542+ PyObject *axis = init_3d_axis (fig);
1543+ /*
15061544 PyObject *gca_kwargs = PyDict_New();
15071545 PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
15081546
@@ -1516,6 +1554,7 @@ bool quiver(const std::vector<NumericX>& x, const std::vector<NumericY>& y, cons
15161554 Py_INCREF(axis);
15171555 Py_DECREF(gca);
15181556 Py_DECREF(gca_kwargs);
1557+ */
15191558
15201559 // plot our boys bravely, plot them strongly, plot them with a wink and clap
15211560 PyObject *plot3 = PyObject_GetAttrString (axis, " quiver" );
@@ -2526,7 +2565,7 @@ inline void set_zlabel(const std::string &str, const std::map<std::string, std::
25262565 if (res) Py_DECREF (res);
25272566}
25282567
2529- inline void grid (bool flag)
2568+ inline void grid (bool flag, const std::map<std::string, std::string>& keywords = std::map<std::string, std::string>() )
25302569{
25312570 detail::_interpreter::get ();
25322571
@@ -2536,10 +2575,16 @@ inline void grid(bool flag)
25362575 PyObject* args = PyTuple_New (1 );
25372576 PyTuple_SetItem (args, 0 , pyflag);
25382577
2539- PyObject* res = PyObject_CallObject (detail::_interpreter::get ().s_python_function_grid , args);
2578+ PyObject* kwargs = PyDict_New ();
2579+ for (auto it = keywords.begin (); it != keywords.end (); ++it) {
2580+ PyDict_SetItemString (kwargs, it->first .c_str (), PyUnicode_FromString (it->second .c_str ()));
2581+ }
2582+
2583+ PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_grid , args, kwargs);
25402584 if (!res) throw std::runtime_error (" Call to grid() failed." );
25412585
25422586 Py_DECREF (args);
2587+ Py_DECREF (kwargs);
25432588 Py_DECREF (res);
25442589}
25452590
0 commit comments