38 #include <QApplication>
39 #include <QGraphicsItem>
40 #include <QGraphicsPolygonItem>
51 static inline array<double, 3> PINdir(
Cell* here,
Cell* ,
Wall* w)
53 assert( (w->GetC1() == here || w->GetC2() == here) &&
"Error in cell <-> wall!" );
54 const double trans = (w->GetC1() == here) ? w->GetTransporters1(1U) : w->GetTransporters2(1U);
55 return trans * w->GetInfluxVector(here);
60 MeshDrawer::MeshDrawer() : m_preferences(make_shared<
prefs_type>()) {}
66 const auto mesh = sim->GetCoreData().m_mesh.get();
67 const ptree& parameters = *sim->GetCoreData().m_parameters;
69 const auto model_group = parameters.get<
string>(
"model.group",
"");
71 const auto cell_colorizer = factory->CreateCellColor(m_preferences->m_cell_color, parameters);
73 const auto& nodes = mesh->GetNodes();
74 const auto loop_nodes = [&nodes](function<void(Node*)> draw) {
75 for (
const auto& n : nodes) {draw(n);}
78 const auto& walls = mesh->GetWalls();
79 const auto loop_walls = [&walls](function<void(Wall*)> draw) {
80 for (
auto const& w : walls) {draw(w);}
83 const auto& cells = mesh->GetCells();
84 const auto loop_cells = [&cells](function<void(Cell*)> draw) {
85 for (
auto c : cells) {draw(c);}
87 const auto loop_nb_cells = [&cells](function<void(Cell*)> draw) {
88 for (
auto c : cells) {
if (c->GetBoundaryType() == BoundaryType::None) {draw(c);}}
91 const auto cell_draw_with_tooltip = [&](
Cell* cell) {
92 const auto& nodes = cell->GetNodes();
93 QPolygonF pa(nodes.size());
95 const unsigned int num_chem = mesh->GetNumChemicals();
98 for (
auto const& n : nodes) {
99 auto pos = (m_preferences->m_mesh_offset + *n) * m_preferences->m_mesh_magnification;
100 pa[cc++] = QPoint(static_cast<int>(pos[0]),
static_cast<int>(pos[1]));
102 const auto c = cell_colorizer(cell);
103 QColor cell_color = QColor::fromRgbF(get<0>(c), get<1>(c), get<2>(c));
105 auto p = scene->addPolygon(pa, m_preferences->m_outline_width >= 0 ?
106 QPen(QColor(m_preferences->m_cell_outline_color.c_str()), m_preferences->m_outline_width) : QPen(Qt::NoPen),
112 QString tool_tip = QString(
"Cell: %1, type: %2 \n").arg(cell->GetIndex()).arg(cell->GetCellType());
113 tool_tip += QString(
"Chemicals (count=%1): ").arg(num_chem);
114 for (
unsigned int i = 0; i < num_chem; i++) {
115 tool_tip += QString(
"%1 ").arg((cell->GetChemical(i))/(cell->GetArea()));
117 QString bt = QString::fromStdString(
ToString(cell->GetBoundaryType()));
118 tool_tip += QString(
"\nArea: %1\nCircumference: %2\nBoundary type: %3")
119 .arg(cell->GetArea()).arg(cell->GetCircumference()).arg(bt);
122 QString nodelist =
"Node_list = { ";
123 for (
auto const& n : nodes) {
124 nodelist += QString(
"%1 ").arg(n->GetIndex());
127 tool_tip +=
"\nNodes: " + nodelist;
130 QString walllist =
"Wall_list = { ";
131 for (
auto const& w : cell->GetWalls()) {
132 walllist += QString(
"%1 ").arg(w->GetIndex());
135 tool_tip +=
"\nWalls: " + walllist;
137 p->setToolTip(tool_tip);
143 const auto cell_draw = [&](
Cell* cell) {
144 const auto& nodes = cell->GetNodes();
145 QPolygonF pa(nodes.size());
149 for (
auto const& n : nodes) {
150 auto pos = (m_preferences->m_mesh_offset + *n) * m_preferences->m_mesh_magnification;
151 pa[cc++] = QPoint(static_cast<int>(pos[0]),
static_cast<int>(pos[1]));
153 const auto c = cell_colorizer(cell);
154 QColor cell_color = QColor::fromRgbF(get<0>(c), get<1>(c), get<2>(c));
156 auto p = scene->addPolygon(pa, m_preferences->m_outline_width >= 0 ?
157 QPen(QColor(m_preferences->m_cell_outline_color.c_str()), m_preferences->m_outline_width) : QPen(Qt::NoPen),
165 const auto cell_draw_center = [&](
Cell* cell) {
166 QRectF rect(-1*m_preferences->m_node_magnification, -1*m_preferences->m_node_magnification,
167 2*m_preferences->m_node_magnification, 2*m_preferences->m_node_magnification);
168 auto disk = scene->addEllipse(rect, QPen(), QColor(
"forest green"));
171 const auto pos = (m_preferences->m_mesh_offset
172 + cell->GetCentroid()) * m_preferences->m_mesh_magnification;
173 disk->setPos(pos[0], pos[1]);
176 const auto cell_draw_fluxes = [&](
Cell* cell) {
178 auto reduce_cell_walls = [](
Cell* cell){
179 std::array<double,3> sum {{0.0, 0.0, 0.0}};
180 for (
auto const& wall : cell->GetWalls()) {
181 sum += (wall->GetC1() == cell) ?
182 PINdir(wall->GetC1(), wall->GetC2(), wall)
183 : PINdir(wall->GetC2(), wall->GetC1(), wall);
187 const auto vec_flux = Normalize(reduce_cell_walls(cell));
190 scene->addItem(arrow);
191 const auto centroid = cell->GetCentroid();
192 const auto from = (m_preferences->m_mesh_offset + centroid
193 - vec_flux * 0.5 * m_preferences->m_arrow_size) * m_preferences->m_mesh_magnification;
194 const auto to = (m_preferences->m_mesh_offset + centroid
195 + vec_flux * 0.5 * m_preferences->m_arrow_size) * m_preferences->m_mesh_magnification;
197 arrow->setPen( QPen(QColor(m_preferences->m_arrow_color.c_str()), m_preferences->m_outline_width));
198 arrow->setLine(from[0], from[1], to[0], to[1]);
199 arrow->setZValue(20);
203 const auto cell_draw_text = [&](
Cell* cell,
const QString& text) {
204 const auto pos = (m_preferences->m_mesh_offset
205 + cell->
GetCentroid()) * m_preferences->m_mesh_magnification;
206 auto ctext = scene->addText(text, QFont(
"Helvetica",
207 m_preferences->m_cell_number_size, QFont::Bold));
208 ctext->setDefaultTextColor( QColor(m_preferences->m_text_color.c_str()) );
209 ctext->setZValue(20);
211 ctext->setPos(pos[0],pos[1]);
214 const auto cell_draw_index = [&](
Cell* cell) {
215 cell_draw_text(cell, QString::number(cell->
GetIndex()));
218 const auto cell_draw_axis = [&](
Cell* cell) {
220 const auto long_axis = Normalize(get<1>(tup));
221 const auto short_axis = Orthogonalize(long_axis);
223 const auto delta = 0.5 * get<2>(tup) * short_axis;
224 const auto from = (m_preferences->m_mesh_offset + centroid - delta) * m_preferences->m_mesh_magnification;
225 const auto to = (m_preferences->m_mesh_offset + centroid + delta) * m_preferences->m_mesh_magnification;
227 auto line = scene->addLine(QLineF(from[0], from[1], to[0], to[1]),
228 QPen(QColor(m_preferences->m_arrow_color.c_str()),2));
234 const auto node_draw = [&](
Node* node) {
235 const auto pos = (m_preferences->m_mesh_offset + *node) * m_preferences->m_mesh_magnification;
237 scene->addItem(item);
241 item->setPos(pos[0], pos[1]);
244 const auto node_draw_index = [&](
Node* node) {
245 const auto pos = (m_preferences->m_mesh_offset + *node) * m_preferences->m_mesh_magnification;
246 auto number = scene->addSimpleText(QString::number(node->GetIndex()),
247 QFont(
"Helvetica", m_preferences->m_node_number_size, QFont::Bold));
250 number->setPen( QPen (m_preferences->m_text_color.c_str()) );
251 number->setZValue(20);
253 number->setPos(pos[0], pos[1]);
256 const auto node_draw_with_tooltip = [&](
Node* node) {
258 const auto pos = (m_preferences->m_mesh_offset + *node) * m_preferences->m_mesh_magnification;
260 scene->addItem(item);
264 item->setPos(pos[0], pos[1]);
267 QString tool_tip = QString(
"Node: %1\n").arg(node->GetIndex());
268 tool_tip += QString(
"Fixed: %1\n").arg(node->IsFixed());
269 tool_tip += QString(
"Sam: %1\n").arg(node->IsSam());
273 tool_tip +=
"Cells: Cell_list = { ";
274 for (
auto const& c : mesh->GetCells()) {
275 if (std::find_if(c->GetNodes().begin(), c->GetNodes().end(),
276 [&node](
Node* n){
return n->GetIndex() == node->GetIndex();}) != c->GetNodes().end()) {
277 tool_tip += QString(
"%1 ").arg(c->GetIndex());
283 tool_tip +=
"Walls: Wall_list = { ";
284 for (
auto const& w : mesh->GetNodeOwningWalls(node)) {
285 tool_tip += QString(
"%1 ").arg(w->GetIndex());
289 item->setToolTip(tool_tip);
295 const auto wall_draw = [&](
Wall* wall) {
298 WallItem* wi1 =
new WallItem(wall, 1, scene, m_preferences->m_outline_width,
299 m_preferences->m_mesh_magnification, m_preferences->m_mesh_offset);
300 WallItem* wi2 =
new WallItem(wall, 2, scene, m_preferences->m_outline_width,
301 m_preferences->m_mesh_magnification, m_preferences->m_mesh_offset);
308 const auto wall_draw_with_tooltip = [&](
Wall* wall) {
311 WallItem* wi1 =
new WallItem(wall, 1, scene, m_preferences->m_outline_width,
312 m_preferences->m_mesh_magnification, m_preferences->m_mesh_offset);
313 WallItem* wi2 =
new WallItem(wall, 2, scene, m_preferences->m_outline_width,
314 m_preferences->m_mesh_magnification, m_preferences->m_mesh_offset);
319 QString wall_tt = QString(
"Wall %1").arg(wall->GetIndex());
320 wall_tt += QString(
"\nType: %1")
322 wall_tt += QString(
"\nCells: { %1 %2 }").arg(wall->GetC1()->GetIndex()).arg(wall->GetC2()->GetIndex());
323 wall_tt += QString(
"\nNodes: { %1 %2 }").arg(wall->GetN1()->GetIndex()).arg(wall->GetN2()->GetIndex());
324 wall_tt += QString(
"\nLength: %1").arg(wall->GetLength());
325 wall_tt += QString(
"\nRestLength: %1").arg(wall->GetRestLength());
326 wall_tt += QString(
"\nStrength: %1").arg(wall->GetStrength());
327 wi1->setToolTip(wall_tt);
328 wi2->setToolTip(wall_tt);
333 const auto boundary_polygon_draw = [&](
Cell* boundary_polygon) {
334 QPolygonF pa(boundary_polygon->GetNodes().size());
337 for (
const auto& n : boundary_polygon->GetNodes()) {
338 const auto pos = (m_preferences->m_mesh_offset + *n) * m_preferences->m_mesh_magnification;
339 pa[cc++] = QPoint(static_cast<int>(pos[0]),
static_cast<int>(pos[1]));
341 auto p = scene->addPolygon(pa,
342 m_preferences->m_outline_width >= 0 ? QPen(QColor(m_preferences->m_cell_outline_color.c_str()), m_preferences->m_outline_width) : QPen(Qt::NoPen),
351 const auto mesh_draw_boundary = [&, mesh]() {
352 boundary_polygon_draw(mesh->GetBoundaryPolygon());
356 if (!m_preferences->m_only_tissue_boundary && m_preferences->m_cells && m_preferences->m_tooltips) {
357 if (m_preferences->m_border_cells)
358 loop_cells(cell_draw_with_tooltip);
360 loop_nb_cells(cell_draw_with_tooltip);
362 if (!m_preferences->m_only_tissue_boundary && m_preferences->m_cells && !m_preferences->m_tooltips) {
363 if (m_preferences->m_border_cells)
364 loop_cells(cell_draw);
366 loop_nb_cells(cell_draw);
368 if (m_preferences->m_cell_centers) {
369 if (m_preferences->m_border_cells)
370 loop_cells(cell_draw_center);
372 loop_nb_cells(cell_draw_center);
374 if (m_preferences->m_fluxes) {
375 if (m_preferences->m_border_cells)
376 loop_cells(cell_draw_fluxes);
378 loop_nb_cells(cell_draw_fluxes);
380 if (m_preferences->m_cell_numbers) {
381 loop_cells(cell_draw_index);
383 if (m_preferences->m_cell_axes) {
384 loop_cells(cell_draw_axis);
386 if (m_preferences->m_cell_strain) {
389 if (m_preferences->m_node_numbers) {
390 loop_nodes(node_draw_index);
392 if (m_preferences->m_walls) {
393 if(m_preferences->m_tooltips) {
394 loop_walls(wall_draw_with_tooltip);
396 loop_walls(wall_draw);
399 if (m_preferences->m_nodes) {
400 if (m_preferences->m_tooltips) {
401 loop_nodes(node_draw_with_tooltip);
403 loop_nodes(node_draw);
406 if (m_preferences->m_only_tissue_boundary) {
407 mesh_draw_boundary();
A cell contains walls and nodes.
Core data used during model execution.
Namespace for miscellaneous utilities.
string ToString(Type w)
Converts a WallType::Type value to corresponding name.
static std::shared_ptr< ComponentFactoryProxy > Create(const string &group_name, bool throw_ok=true)
Create a factory proxy.
Namespace for SimPT shell package.
Namespace for the core simulator.
void Draw(std::shared_ptr< SimPT_Sim::SimInterface > sim, QGraphicsScene *scene)
Draws the mesh to QGraphicsScene.
BoundaryType enumeration class.
Proxy for dealing with the factories.
Preferences for graphics viewer.
Interface for MergedPreferences.
int GetIndex() const
Return the index.
std::array< double, 3 > GetCentroid() const
Return the centroid position.
Interface for MeshDrawer.
Arrow composed and drawn with Qt primitives.
Interface/Implementation for ReduceCellWalls.
String manipulation utilities.
std::tuple< double, std::array< double, 3 >, double > GetEllipseAxes() const
Calculate axes (length and direction) area moment of inertia ellipse.
GeoData GetGeoData() const
Return GeData (area, centroid, area moment of inertia).
Graphic wrapper for Node.
A cell wall, runs between cell corner points and consists of wall elements.
WallItem shows transporter concentrations at one side of the wall.