Skip to content

Commit 80bc9cd

Browse files
sapphouslava
authored andcommitted
Add 3D quiver support
1 parent 70d508f commit 80bc9cd

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

matplotlibcpp.h

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,92 @@ bool quiver(const std::vector<NumericX>& x, const std::vector<NumericY>& y, cons
12021202
return res;
12031203
}
12041204

1205+
template<typename NumericX, typename NumericY, typename NumericZ, typename NumericU, typename NumericW, typename NumericV>
1206+
bool quiver(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::vector<NumericZ>& z, const std::vector<NumericU>& u, const std::vector<NumericW>& w, const std::vector<NumericV>& v, const std::map<std::string, std::string>& keywords = {})
1207+
{
1208+
//set up 3d axes stuff
1209+
static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr;
1210+
if (!mpl_toolkitsmod) {
1211+
detail::_interpreter::get();
1212+
1213+
PyObject* mpl_toolkits = PyString_FromString("mpl_toolkits");
1214+
PyObject* axis3d = PyString_FromString("mpl_toolkits.mplot3d");
1215+
if (!mpl_toolkits || !axis3d) { throw std::runtime_error("couldnt create string"); }
1216+
1217+
mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
1218+
Py_DECREF(mpl_toolkits);
1219+
if (!mpl_toolkitsmod) { throw std::runtime_error("Error loading module mpl_toolkits!"); }
1220+
1221+
axis3dmod = PyImport_Import(axis3d);
1222+
Py_DECREF(axis3d);
1223+
if (!axis3dmod) { throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!"); }
1224+
}
1225+
1226+
//assert sizes match up
1227+
assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size() && x.size() == z.size() && x.size() == v.size() && u.size() == v.size());
1228+
1229+
//set up parameters
1230+
detail::_interpreter::get();
1231+
1232+
PyObject* xarray = detail::get_array(x);
1233+
PyObject* yarray = detail::get_array(y);
1234+
PyObject* zarray = detail::get_array(z);
1235+
PyObject* uarray = detail::get_array(u);
1236+
PyObject* warray = detail::get_array(w);
1237+
PyObject* varray = detail::get_array(v);
1238+
1239+
PyObject* plot_args = PyTuple_New(6);
1240+
PyTuple_SetItem(plot_args, 0, xarray);
1241+
PyTuple_SetItem(plot_args, 1, yarray);
1242+
PyTuple_SetItem(plot_args, 2, zarray);
1243+
PyTuple_SetItem(plot_args, 3, uarray);
1244+
PyTuple_SetItem(plot_args, 4, warray);
1245+
PyTuple_SetItem(plot_args, 5, varray);
1246+
1247+
// construct keyword args
1248+
PyObject* kwargs = PyDict_New();
1249+
for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1250+
{
1251+
PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1252+
}
1253+
1254+
//get figure gca to enable 3d projection
1255+
PyObject *fig =
1256+
PyObject_CallObject(detail::_interpreter::get().s_python_function_figure,
1257+
detail::_interpreter::get().s_python_empty_tuple);
1258+
if (!fig) throw std::runtime_error("Call to figure() failed.");
1259+
1260+
PyObject *gca_kwargs = PyDict_New();
1261+
PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
1262+
1263+
PyObject *gca = PyObject_GetAttrString(fig, "gca");
1264+
if (!gca) throw std::runtime_error("No gca");
1265+
Py_INCREF(gca);
1266+
PyObject *axis = PyObject_Call(
1267+
gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs);
1268+
1269+
if (!axis) throw std::runtime_error("No axis");
1270+
Py_INCREF(axis);
1271+
Py_DECREF(gca);
1272+
Py_DECREF(gca_kwargs);
1273+
1274+
//plot our boys bravely, plot them strongly, plot them with a wink and clap
1275+
PyObject *plot3 = PyObject_GetAttrString(axis, "quiver");
1276+
if (!plot3) throw std::runtime_error("No 3D line plot");
1277+
Py_INCREF(plot3);
1278+
PyObject* res = PyObject_Call(
1279+
plot3, plot_args, kwargs);
1280+
if (!res) throw std::runtime_error("Failed 3D plot");
1281+
Py_DECREF(plot3);
1282+
Py_DECREF(axis);
1283+
Py_DECREF(kwargs);
1284+
Py_DECREF(plot_args);
1285+
if (res)
1286+
Py_DECREF(res);
1287+
1288+
return res;
1289+
}
1290+
12051291
template<typename NumericX, typename NumericY>
12061292
bool stem(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
12071293
{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy