29 #include <boost/iterator/iterator_facade.hpp>
30 #include <boost/optional/optional.hpp>
31 #include <boost/property_tree/detail/ptree_implementation.hpp>
54 m_ptree.put_child(
"parameters", ptree());
55 m_ptree.put_child(
"mesh", BuildTwoSquaresMesh(chemical_count).ToPtree());
60 : m_mesh(new
EditableMesh(pt.get_child(
"mesh"))), m_moving_node(false),
64 if (
auto parameters = pt.get_child_optional(
"parameters")) {
65 m_ptree.put_child(
"parameters", parameters.get());
67 m_ptree.put_child(
"parameters", ptree());
69 m_ptree.put_child(
"mesh", m_mesh->
GetMesh()->ToPtree());
77 Mesh EditControlLogic::BuildTwoSquaresMesh(
unsigned int chemical_count)
79 Mesh mesh(chemical_count);
81 auto node_0 = mesh.BuildNode(0, {{ +5.0, 0.0 }},
true);
82 mesh.BuildNode(1, {{ +5.0, +10.0 }},
true);
83 mesh.BuildNode(2, {{ -5.0, +10.0 }},
true);
84 auto node_3 = mesh.BuildNode(3, {{ -5.0, 0.0 }},
true);
85 mesh.BuildNode(4, {{ -5.0, -10.0 }},
true);
86 mesh.BuildNode(5, {{ +5.0, -10.0 }},
true);
88 Cell* cell_0 = mesh.BuildCell(0, {{ 0, 1, 2, 3 }});
89 Cell* cell_1 = mesh.BuildCell(1, {{ 0, 3, 4, 5 }});
90 Cell* cell_bp = mesh.BuildBoundaryPolygon({{ 0, 1, 2, 3, 4, 5}});
92 Wall* wall_0 = mesh.BuildWall(0, node_3, node_0, cell_1, cell_bp);
93 Wall* wall_1 = mesh.BuildWall(1, node_0, node_3, cell_0, cell_bp);
94 Wall* wall_2 = mesh.BuildWall(2, node_3, node_0, cell_0, cell_1);
96 cell_0->
GetWalls().push_back(wall_1);
97 cell_0->
GetWalls().push_back(wall_2);
98 cell_1->
GetWalls().push_back(wall_0);
99 cell_1->
GetWalls().push_back(wall_2);
100 cell_bp->
GetWalls().push_back(wall_0);
101 cell_bp->
GetWalls().push_back(wall_1);
103 mesh.ConstructNeighborList(mesh.GetBoundaryPolygon());
104 mesh.UpdateNodeOwningNeighbors(mesh.GetBoundaryPolygon());
105 for (
auto cell : mesh.GetCells()) {
106 mesh.ConstructNeighborList(cell);
107 mesh.UpdateNodeOwningNeighbors(cell);
115 if (!m_selected_nodes.empty()) {
116 for (
Node* n : m_selected_nodes) {
117 ptree node_pt = n->NodeAttributes::ToPtree();
118 n->NodeAttributes::ReadPtree(UpdatePTree(node_pt, pt));
121 else if (!m_selected_walls.empty()) {
122 for (
Wall* w : m_selected_walls) {
123 ptree wall_pt = w->WallAttributes::ToPtree();
124 w->WallAttributes::ReadPtree(UpdatePTree(wall_pt, pt));
127 else if (!m_selected_cells.empty()) {
128 for (
Cell* c : m_selected_cells) {
129 ptree cell_pt = c->CellAttributes::ToPtree();
130 c->CellAttributes::ReadPtree(UpdatePTree(cell_pt, pt));
133 m_ptree_dirty =
true;
139 if (!m_selected_cells.empty()) {
140 for (
Cell* c : m_selected_cells) {
142 ptree cell_pt = c->CellAttributes::ToPtree();
144 c->CellAttributes::ReadPtree(new_pt);
147 else if (!m_selected_nodes.empty()) {
148 for (
Node* n : m_selected_nodes) {
150 ptree node_pt = n->NodeAttributes::ToPtree();
152 n->NodeAttributes::ReadPtree(new_pt);
155 else if (!m_selected_walls.empty()) {
156 for (
Wall* w : m_selected_walls) {
158 ptree wall_pt = w->WallAttributes::ToPtree();
160 w->WallAttributes::ReadPtree(new_pt);
164 assert(
false &&
"No entities were selected.");
167 m_ptree_dirty =
true;
174 auto newCell = m_mesh->
CreateCell(node1, node2, newPoint);
176 if (newCell !=
nullptr) {
178 m_ptree_dirty =
true;
187 if (cell->HasBoundaryWall()) {
200 m_ptree_dirty =
true;
208 m_ptree_dirty =
true;
219 m_selected_nodes.clear();
220 m_selected_walls.clear();
221 m_selected_cells.clear();
226 const ptree& EditControlLogic::GetParameters()
const
228 return m_ptree.get_child(
"parameters");
234 m_ptree_dirty =
true;
235 m_moving_node =
true;
236 emit
Moved(node, x, y);
247 m_ptree.put_child(
"mesh", m_mesh->
GetMesh()->ToPtree());
257 m_ptree_dirty =
true;
263 m_selected_cells = cells;
268 std::string info =
"Cells selected: "
269 + to_string(m_selected_cells.front()->GetIndex());
270 for (
auto it =
next(m_selected_cells.begin()); it != m_selected_cells.end(); it++) {
271 info +=
", " + to_string((*it)->GetIndex());
278 m_selected_walls.clear();
279 for (
const Edge& edge : edges) {
282 && std::find(m_selected_walls.begin(), m_selected_walls.end(), w) == m_selected_walls.end()) {
283 m_selected_walls.push_back(w);
287 m_selected_walls.sort([](
Wall* w1,
Wall* w2){
return w1->GetIndex() < w2->GetIndex();});
290 std::string info =
"Walls selected: "
291 + to_string(m_selected_walls.front()->GetIndex());
292 for (
auto it =
next(m_selected_walls.begin()); it != m_selected_walls.end(); it++) {
293 info +=
", " + to_string((*it)->GetIndex());
300 assert(nodes.size() > 0 &&
"No nodes were selected.");
302 m_selected_nodes = nodes;
304 m_selected_nodes.sort([](
Node* n1,
Node* n2){
return n1->GetIndex() < n2->GetIndex();});
307 string info =
"Nodes selected: "
308 + to_string(m_selected_nodes.front()->GetIndex());
309 for (
auto it =
next(m_selected_nodes.begin()); it != m_selected_nodes.end(); it++) {
310 info +=
", " + to_string((*it)->GetIndex());
317 m_ptree.put_child(
"parameters", pt);
323 vector<Cell*> cells = m_mesh->
SplitCell(node1, node2);
325 if (cells.size() > 1) {
326 m_ptree_dirty =
true;
335 Node* node1,
Node* node2,
bool modified)
337 vector<Cell*> cells = m_mesh->
SplitCell(cell, node1, node2);
339 if (cells.size() > 1) {
340 m_ptree_dirty =
true;
352 m_ptree_dirty =
true;
360 m_moving_node =
false;
366 ptree EditControlLogic::UpdatePTree(ptree pt1, ptree pt2)
368 assert(pt1.data() !=
"?" &&
"The data of the first ptree should be known completely.");
371 if (pt1.data() != pt2.data()) {
372 pt = ptree(pt2.data());
375 pt = ptree(pt1.data());
378 if (pt1.size() == 0) {
382 ptree::const_iterator it1 = pt1.begin();
383 ptree::const_iterator it2 = pt2.begin();
384 while (it1 != pt1.end() && it2 != pt2.end()) {
385 if (it1->first == it2->first) {
386 if (it2->second.data() !=
"?") {
387 pt.add_child(it1->first, UpdatePTree(it1->second, it2->second));
391 else if (pt1.count(it1->first) < pt2.count(it2->first)) {
395 pt.add_child(it1->first, it1->second);
400 else if (it1->first < it2->first) {
401 if (it1->second.data() !=
"?") {
402 pt.add_child(it1->first, it1->second);
407 if (it2->second.data() !=
"?") {
408 pt.add_child(it2->first, it2->second);
414 for (ptree::const_iterator it = it1; it != pt1.end(); ++it) {
415 if (it1->second.data() !=
"?") {
416 pt.add_child(it->first, it->second);
419 for (ptree::const_iterator it = it2; it != pt2.end(); ++it) {
420 if (it2->second.data() !=
"?") {
421 pt.add_child(it->first, it->second);
void StopMoveNode()
Stop moving a node after moving it.
void SetParameters(const boost::property_tree::ptree &)
Set parameters ptree.
A cell contains walls and nodes.
Namespace for SimPT tissue editor package.
bool MoveNode(Node *node, double x, double y)
See EditableMesh::DisplaceCell for more information.
Namespace for miscellaneous utilities.
void DeleteCells(const std::list< Cell * > &cells)
Delete the given cells in the mesh.
static void FillPTree(boost::property_tree::ptree &pt1, const boost::property_tree::ptree &pt2)
Fill the first ptree with the second ptree.
const std::list< Wall * > & GetWalls() const
Access the cell's walls.
virtual ~EditControlLogic()
Destructor.
Cell * CreateCell(Node *node1, Node *node2, const QPointF &newPoint)
Creates a new cell with the two given nodes and a third new point.
Namespace for the core simulator.
bool DeleteTwoDegreeNode(Node *node)
Deletes the given node from the mesh (which should stay consistent).
An Edge connects two nodes and is ambidextrous.
const boost::property_tree::ptree & ToPTree()
Get the PTree associated with the mesh.
void CopyAttributes(const boost::property_tree::ptree &pt)
Copy the given attributes to the selected cells.
void StatusInfoChanged(const std::string &info)
Emitted when certain info about the logic has changed.
void Modified()
Emitted when data has been modified.
std::shared_ptr< SimPT_Sim::Mesh > & GetMesh()
Get the mesh.
void SelectEdges(const std::list< Edge > &edges)
Select the given edges.
void DeleteCells(const std::list< Cell * > &cells)
Deletes the given cell from the mesh.
Node * SplitEdge(const Edge &edge)
Split a given edge at the center.
void ChangeAttributes(const boost::property_tree::ptree &pt)
Change the attributes of the selected items to the attributes in the given ptree. ...
std::vector< Cell * > SplitCell(Cell *cell, Node *node1, Node *node2, bool modified=false)
See EditableMesh::SplitCell for more information.
void SelectNodes(const std::list< Node * > &nodes)
Select the given nodes.
void SelectCells(const std::list< Cell * > &cells)
Select the given cells.
void StoppedMoving()
Emitted when data has been modified.
std::vector< Cell * > SplitCell(Node *node1, Node *node2)
Does the same as SplitCell, but finds the correct cell that should be split.
void Moved(Node *node, double x, double y)
Emitted when the given node has been moved to the given coordinates.
void Deselect()
Deselect the selected items.
int GetIndex() const
Return the index.
bool DeleteCell(Cell *cell)
Delete the given cell in the mesh.
bool DisplaceNode(Node *node, double x, double y)
Place a node at the given coordinates.
Cell * CreateCell(Node *node1, Node *node2, const QPointF &newPoint)
See EditableMesh::CreateCell for more information.
Structure of cells; key data structure.
void ReplaceCell(Cell *cell, std::list< QPolygonF > newCells)
See EditableMesh::ReplaceCell for more information.
CircularIterator< T > next(CircularIterator< T > i)
Helper yields the position the iterator would have if moved forward (in circular fashion) by 1 positi...
EditControlLogic(unsigned int chemical_count)
Constructs a default tissue, which is an upward triangle.
An editable mesh with actions to alter the construction of the mesh.
Node * SplitEdge(const Edge &edge)
Split a given edge at the center.
Interface for LeafControlLogic.
A cell wall, runs between cell corner points and consists of wall elements.
void SelectionChanged()
Emitted when selection has changed.
bool DeleteNode(Node *node)
Delete the given node in the mesh.
void ReplaceCell(Cell *cell, std::list< QPolygonF > newCells)
Replace a given cell with a set of new cells.