Skip to content

Commit 2173ff2

Browse files
committed
Added support for exporing plot object data from Python.
1 parent 3ed92a0 commit 2173ff2

11 files changed

Lines changed: 142 additions & 59 deletions

File tree

FEBioStudio/DataFieldSelector.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,9 @@ CPlotObjectDataSelector::CPlotObjectDataSelector(Post::FEPostModel::PlotObject*
223223

224224
void CPlotObjectDataSelector::BuildMenu(QMenu* menu)
225225
{
226-
std::vector<PlotObjectData*>& data = m_po->m_data;
227-
for (int i = 0; i < (int)data.size(); ++i)
226+
for (int i = 0; i < (int) m_po->DataCount(); ++i)
228227
{
229-
ModelDataField& d = *data[i];
228+
PlotObjectData& d = *m_po->GetData(i);
230229
int dataClass = d.DataClass();
231230
int dataComponents = d.components(TENSOR_SCALAR);
232231
if (dataComponents > 0)

FEBioStudio/GraphWindow.cpp

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,44 +2262,7 @@ void CModelGraphWindow::TrackObjectHistory(int nobj, float* pval, int nfield, in
22622262

22632263
for (int j = 0; j < nn; ++j)
22642264
{
2265-
Post::FEState* state = fem.GetState(j + nmin);
2266-
Post::OBJECTDATA& pointData = state->GetObjectData(nobj);
2267-
2268-
Post::ObjectData* data = pointData.data;
2269-
2270-
// get the data ID
2271-
int ndata = FIELD_CODE(nfield);
2272-
2273-
// get the component
2274-
int ncomp = FIELD_COMP(nfield);
2275-
2276-
Post::ModelDataField* dataField = po->m_data[ndata];
2277-
2278-
float val = 0.f;
2279-
2280-
switch (dataField->Type())
2281-
{
2282-
case DATA_SCALAR:
2283-
{
2284-
val = data->get<float>(ndata);
2285-
}
2286-
break;
2287-
case DATA_VEC3:
2288-
{
2289-
vec3f v = data->get<vec3f>(ndata);
2290-
val = component(v, ncomp);
2291-
}
2292-
break;
2293-
case DATA_MAT3:
2294-
{
2295-
mat3f v = data->get<mat3f>(ndata);
2296-
val = component(v, ncomp);
2297-
}
2298-
break;
2299-
default:
2300-
assert(false);
2301-
}
2302-
2265+
float val = fem.EvaluatePlotObjectData(nobj, j + nmin, nfield);
23032266
pval[j] = val;
23042267
}
23052268
}

PostGL/GLPlotObjectGlyph.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ Post::GLPlotObjectVector::GLPlotObjectVector(Post::FEPostModel::PointObject* po)
3838

3939
std::vector<std::string> nameList;
4040
size_t l = 0;
41-
for (int i = 0; i < po->m_data.size(); ++i)
41+
for (int i = 0; i < po->DataCount(); ++i)
4242
{
43-
Post::PlotObjectData* pd = po->m_data[i];
43+
Post::PlotObjectData* pd = po->GetData(i);
4444
if (pd->Type() == DATA_VEC3)
4545
{
4646
std::string name = pd->GetName();
@@ -81,9 +81,9 @@ void Post::GLPlotObjectVector::Update(int ntime, float dt, bool breset)
8181
Post::OBJ_POINT_DATA& data = state->m_objPt[m_po->m_id];
8282

8383
int nvec = GetIntValue(DATA_FIELD);
84-
for (int i = 0, n = 0; i < m_po->m_data.size(); ++i)
84+
for (int i = 0, n = 0; i < m_po->DataCount(); ++i)
8585
{
86-
Post::PlotObjectData* pd = m_po->m_data[i];
86+
Post::PlotObjectData* pd = m_po->GetData(i);
8787
if (pd->Type() == DATA_VEC3)
8888
{
8989
if (nvec == n)

PostLib/FEDataField.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ ModelDataField::ModelDataField(FEPostModel* fem, DATA_TYPE ntype, DATA_FORMAT nf
4141
m_nclass = ncls;
4242
m_flag = flag;
4343
m_arraySize = 0;
44+
m_nfield = -1;
4445
}
4546

4647
ModelDataField::~ModelDataField() {}

PostLib/FEKinemat.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,11 @@ bool FEKinemat::BuildStates(Post::FEPostModel* pfem)
167167

168168
PlotObjectData* data1 = new PlotObjectData(&fem, DATA_VEC3);
169169
data1->SetName("position");
170-
ob->m_data.push_back(data1);
170+
ob->AddData(data1);
171171

172172
PlotObjectData* data2 = new PlotObjectData(&fem, DATA_MAT3);
173173
data2->SetName("rotation");
174-
ob->m_data.push_back(data2);
174+
ob->AddData(data2);
175175

176176
fem.AddPointObject(ob);
177177
}

PostLib/FEPostModel.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,37 @@ FEPostModel::PlotObject* FEPostModel::GetPlotObject(int n)
14771477
return nullptr;
14781478
}
14791479

1480+
int FEPostModel::GetPlotObjectIndex(FEPostModel::PlotObject* po)
1481+
{
1482+
for (int i = 0; i < PointObjects(); ++i)
1483+
{
1484+
if (m_Points[i].get() == po) return i;
1485+
}
1486+
1487+
int N0 = PointObjects();
1488+
for (int i = 0; i < LineObjects(); ++i)
1489+
{
1490+
if (m_Lines[i].get() == po) return i + N0;
1491+
}
1492+
1493+
return -1;
1494+
}
1495+
1496+
FEPostModel::PlotObject* FEPostModel::FindPlotObject(const std::string& name)
1497+
{
1498+
for (int i=0; i<PointObjects(); ++i)
1499+
{
1500+
if (m_Points[i]->GetName() == name) return m_Points[i].get();
1501+
}
1502+
1503+
for (int i = 0; i < LineObjects(); ++i)
1504+
{
1505+
if (m_Lines[i]->GetName() == name) return m_Lines[i].get();
1506+
}
1507+
1508+
return nullptr;
1509+
}
1510+
14801511
int FEPostModel::PointObjects() const
14811512
{
14821513
return (int)m_Points.size();

PostLib/FEPostModel.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ SOFTWARE.*/
3434
#include <FSCore/box.h>
3535
#include <vector>
3636
#include <memory>
37+
#include "constants.h"
3738

3839
namespace Post {
3940

@@ -84,6 +85,24 @@ class FEPostModel
8485
//! Find the index of object data with the given name
8586
int FindObjectDataIndex(const std::string& name) const;
8687

88+
ModelDataField* GetObjectData(int n) { return m_data[n]; }
89+
ModelDataField* FindObjectData(const std::string& name)
90+
{
91+
int n = FindObjectDataIndex(name);
92+
if (n < 0) return nullptr;
93+
return m_data[n];
94+
}
95+
96+
void AddData(PlotObjectData* po)
97+
{
98+
po->SetFieldID(BUILD_FIELD(DATA_CLASS::OBJECT_DATA, m_data.size(), 0));
99+
m_data.push_back(po);
100+
}
101+
102+
PlotObjectData* GetData(int n) { return m_data[n]; }
103+
104+
size_t DataCount() const { return m_data.size(); }
105+
87106
public:
88107
//! Unique identifier for the plot object
89108
int m_id;
@@ -94,6 +113,7 @@ class FEPostModel
94113
//! Rotation of the plot object
95114
quatd m_rot;
96115

116+
private:
97117
//! Vector of data associated with the plot object
98118
std::vector<PlotObjectData*> m_data;
99119
};
@@ -299,6 +319,9 @@ class FEPostModel
299319
//! Check if the field code is valid for the given state
300320
bool IsValidFieldCode(int nfield, int nstate);
301321

322+
float EvaluatePlotObjectData(int nobj, int ntime, int nfield);
323+
float EvaluatePlotObject(PlotObject* po, ModelDataField& data, int comp, int ntime);
324+
302325
public:
303326
//! Add a dependant object that will be notified of model changes
304327
void AddDependant(FEModelDependant* pc);
@@ -345,6 +368,10 @@ class FEPostModel
345368
//! Get a plot object by index
346369
PlotObject* GetPlotObject(int n);
347370

371+
int GetPlotObjectIndex(PlotObject* po);
372+
373+
PlotObject* FindPlotObject(const std::string& name);
374+
348375
//! Get the number of point objects
349376
int PointObjects() const;
350377
//! Add a point object

PostLib/FEState.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,11 @@ FEState::FEState(float time, FEPostModel* fem, FSMesh* pmesh) : m_fem(fem), m_me
165165
di.m_r1 = po.m_r1;
166166
di.m_r2 = po.m_r2;
167167

168-
int ndata = (int)po.m_data.size();
168+
int ndata = (int)po.DataCount();
169169
di.data = new ObjectData;
170170
for (int j = 0; j < ndata; ++j)
171171
{
172-
Post::PlotObjectData& dj = *po.m_data[j];
172+
Post::PlotObjectData& dj = *po.GetData(j);
173173

174174
switch (dj.Type())
175175
{
@@ -209,11 +209,11 @@ void FEState::AddPointObjectData()
209209

210210
di.m_rt = po.m_rt;
211211

212-
int ndata = (int)po.m_data.size();
212+
int ndata = (int)po.DataCount();
213213
di.data = new ObjectData;
214214
for (int j = 0; j < ndata; ++j)
215215
{
216-
Post::PlotObjectData& dj = *po.m_data[j];
216+
Post::PlotObjectData& dj = *po.GetData(j);
217217

218218
switch (dj.Type())
219219
{

PostLib/evaluate.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2932,3 +2932,56 @@ mat3f FEPostModel::EvaluateElemTensor(int n, int ntime, int nten, int ntype)
29322932

29332933
return m;
29342934
}
2935+
2936+
float FEPostModel::EvaluatePlotObjectData(int nobj, int ntime, int nfield)
2937+
{
2938+
PlotObject* po = GetPlotObject(nobj);
2939+
2940+
Post::FEState* state = GetState(ntime);
2941+
Post::OBJECTDATA& pointData = state->GetObjectData(nobj);
2942+
2943+
Post::ObjectData* data = pointData.data;
2944+
2945+
// get the data ID
2946+
int ndata = FIELD_CODE(nfield);
2947+
2948+
// get the component
2949+
int ncomp = FIELD_COMP(nfield);
2950+
2951+
Post::ModelDataField* dataField = po->GetData(ndata);
2952+
2953+
float val = 0.f;
2954+
2955+
switch (dataField->Type())
2956+
{
2957+
case DATA_SCALAR:
2958+
{
2959+
val = data->get<float>(ndata);
2960+
}
2961+
break;
2962+
case DATA_VEC3:
2963+
{
2964+
vec3f v = data->get<vec3f>(ndata);
2965+
val = component(v, ncomp);
2966+
}
2967+
break;
2968+
case DATA_MAT3:
2969+
{
2970+
mat3f v = data->get<mat3f>(ndata);
2971+
val = component(v, ncomp);
2972+
}
2973+
break;
2974+
default:
2975+
assert(false);
2976+
}
2977+
2978+
return val;
2979+
}
2980+
2981+
float FEPostModel::EvaluatePlotObject(FEPostModel::PlotObject* po, ModelDataField& data, int comp, int ntime)
2982+
{
2983+
int nobj = GetPlotObjectIndex(po);
2984+
if (nobj < 0) return 0.f;
2985+
int nfield = data.GetFieldID() + comp;
2986+
return EvaluatePlotObjectData(nobj, ntime, nfield);
2987+
}

PyLib/PyFBSPost.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ void init_FBSPost(py::module& m)
173173
.def("Enabled", &Material::enabled, "Checks if the material is enabled.")
174174
;
175175

176+
py::class_<FEPostModel::PlotObject>(post, "PlotObject")
177+
.def("Name", &FEPostModel::PlotObject::GetName, "Returns the name of the plot object.")
178+
.def("GetDataField", &FEPostModel::PlotObject::FindObjectData, "Returns the name of the plot object.")
179+
;
180+
176181
py::class_<FEPostModel>(post, "PostModel", DOC(Post, FEPostModel))
177182
.def("Materials", &FEPostModel::Materials, DOC(Post, FEPostModel, Materials))
178183
.def("Material", &FEPostModel::GetMaterial, DOC(Post, FEPostModel, GetMaterial), py::return_value_policy::reference)
@@ -194,7 +199,10 @@ void init_FBSPost(py::module& m)
194199
self.Evaluate(field.GetFieldID() | component, time);
195200
return self.GetState(time);
196201
}, "Evaluates the model at a specific time step. Returns a reference to the state and updates the values stored in the state's member variables.",
197-
py::return_value_policy::reference);
202+
py::return_value_policy::reference)
203+
.def("GetPlotObject", &FEPostModel::FindPlotObject, py::return_value_policy::reference)
204+
.def("EvaluatePlotObject", &FEPostModel::EvaluatePlotObject, py::return_value_policy::reference)
205+
;
198206

199207
py::enum_<Data_Tensor_Type>(post, "DataTensorType")
200208
.value("DATA_SCALAR", Data_Tensor_Type::TENSOR_SCALAR)

0 commit comments

Comments
 (0)