/** Check that given edge is in current sector */ bool NodeNav::isEdgeInSector( GEdge * edge) const { GNode *n = otherEnd( edge); /* item corresponding to other (than node_priv) node */ if ( isNullP( n) || sector() == UNDEF_SECTOR) return false; NodeItem *item = n->item(); // Both points in current node's coordinates QPointF p_center = node_priv->item()->boundingRect().center(); QPointF s_center = node_priv->item()->mapFromItem( item, item->boundingRect().center()); qreal angle = QLineF( p_center, s_center).angle(); qreal max_angle = sectorMaxAngle(); qreal min_angle = sectorMinAngle(); if ( angle > 270 && sector() == RIGHT_SECTOR) { max_angle +=360; } if ( angle < 90 && sector() == RIGHT_SECTOR) { min_angle -=360; } if ( angle <= max_angle && angle >= min_angle) return true; return false; }
// Graph layout stuff void MainWindow::applyRandomLayout() { RandomNumberGenerator rng(QDateTime::currentMSecsSinceEpoch()); // Define the topology to work in QRectF rc(m_graphView->visibleRegion().boundingRect()); rc.adjust(-10.0f, -10.0f, -10.0f, -10.0f); rc.moveTo(-rc.width() / 2.0f, -rc.height() / 2.0f); Topology top(rng, rc.left(), rc.top(), rc.right(), rc.bottom()); // Apply the layout boost::random_graph_layout(m_graph, get(&NodeProperties::pos, m_graph), top); // Forward the calculated values into the graphics objects std::pair<DigraphVertexIterator, DigraphVertexIterator> iterators = boost::vertices(m_graph); DigraphVertexIterator it = iterators.first; for (; it != iterators.second; ++it) { TopologicalPoint pt = m_graph[*it].pos; NodeItem* node = m_graph[*it].item; node->setPos(pt[0], pt[1]); } }
void NodeMove::redo() { NodeItem *item = scene->findItem(node_id); item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false); item->setPos(_new); scene->updateConnections(item); item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); //scene->update(); }
void DeleteNode::redo() { NodeItem *item = scene->findItem(QString::fromStdString(node_id)); Q_ASSERT(item != 0); scene->disconnect(item); scene->node_items.remove(item->getId()); Node *n = item->getNode(); delete item; scene->model->removeNode(n); //deletes n }
/* void NodeItem::mouseMoveEvent(QGraphicsSceneDragDropEvent *event) { event->setAccepted(true); } void ParameterItem::mousePressEvent(QGraphicsSceneDragDropEvent *event) { event->setAccepted(false); } */ void ParameterItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ) { if (event->button() == Qt::LeftButton) { setColor(Qt::darkCyan); // force my box to snap to grid, just truncate the pixel number and // snap to the next lowest grid value if (fmod(_location.x(),_gridSpace) >_gridSpace/2) _location.setX( ( static_cast<int>(_location.x()+_gridSpace) / _gridSpace) * _gridSpace ); else _location.setX( ( static_cast<int>(_location.x()) / _gridSpace) * _gridSpace ); if (fmod(_location.y(),_gridSpace) >_gridSpace/2) _location.setY( ( static_cast<int>(_location.y()+_gridSpace) / _gridSpace) * _gridSpace ); else _location.setY( ( static_cast<int>(_location.y()) / _gridSpace) * _gridSpace ); foreach (QGraphicsItem *item, collidingItems()) { if (item->type() ==GroupItem::Type){ this->setPos(mapToItem(item,0,0)); setParentItem(item); } else { this->setPos(mapToScene(0,0)); this->setParentItem(0); } } if (scene()->itemAt(_location)){ switch (scene()->itemAt(_location)->type()){ case GroupItem::Type: //Group setParentItem(scene()->itemAt(_location)); this->setPos(_location-(this->parentItem()->pos())); break; case NodeItem::Type: //Node or Test NodeItem *node; node=qgraphicsitem_cast<NodeItem *>(scene()->itemAt(_location)); node->addParamItem(this); scene()->removeItem(this); break; case 8: //TextItem -> check for parent if (scene()->itemAt(_location)->parentItem()->type() ==NodeItem::Type){ //Node or Test NodeItem *node; node=qgraphicsitem_cast<NodeItem *>(scene()->itemAt(_location)->parentItem()); node->addParamItem(this); scene()->removeItem(this); } break; } } event->setAccepted(true);// tell the base class we are handling this event }
void ChangeParameters::undo() { NodeItem *item = scene->findItem(id); Q_ASSERT(item != 0); item->getNode()->deinit(); item->restoreParameters(before); SimulationParameters sp = scene->simulation->getSimulationParameters(); item->getNode()->init(sp.start + seconds(sp.dt), sp.stop, sp.dt); item->updatePorts(); //scene->update(); scene->updateConnections(item); }
void DeleteNode::undo() { Node *node = scene->node_reg->createNode(node_class); scene->model->addNode(node_id, node); NodeItem *nitem = new NodeItem(node); nitem->restoreParameters(parameters); SimulationParameters sp = scene->simulation->getSimulationParameters(); node->init(sp.start + seconds(sp.dt), sp.stop, sp.dt); nitem->updatePorts(); nitem->setPos(pos); scene->add(nitem); //scene->update(); }
void ChangeParameters::redo() { if (first_redo) { first_redo = false; return; } NodeItem *item = scene->findItem(id); Q_ASSERT(item != 0); item->getNode()->deinit(); item->restoreParameters(after); SimulationParameters sp = scene->simulation->getSimulationParameters(); item->getNode()->init(sp.start + seconds(sp.dt), sp.stop, sp.dt); item->updatePorts(); //scene->update(); scene->updateConnections(item); }
/*!\brief reimplementation of the dropEvent * * Creates a node item if a node is dropped in the view. * The neccessary nodeinformation is fetched during the mousepressaction for the drag event * in RxDev::selectionHandle_availableNodes. */ void LaunchFileView::dropEvent(QDropEvent *event) { NodeItem * newNode; newNode = new NodeItem(selectedNodeName,selectedNodePackage,selectedNodeSubscriptions, selectedNodePublications,selectedNodeServices,selectedNodeParameters); newNode->setLocation(mapToScene(event->pos())); newNode->setPos(mapToScene(event->pos())); if (newNode->getNodeData()==true){ scene()->addItem(newNode); } selectedBox->setColor(Qt::black); selectedBox= newNode; }
/** Get edge to the left of given edge */ GEdge * NodeNav::edgeInDir( GEdge * edge, NavDirection dir) const { /* Applicable only for top and bottom sectors */ if ( !isDirApplicable( dir, sector())) { return NULL; } GNode *n = otherEnd( edge); /* item corresponding to other (than node_priv) node */ if ( isNullP( n)) return NULL; NodeItem *item = n->item(); // in current node's coordinates QPointF edge_point = node()->item()->mapFromItem( item, item->boundingRect().center()); GEdge *res = NULL; qreal min_delta = 0; /** For each edge */ for ( Node::EdgeIter e_iter = node()->edgesBegin(), e_end = node()->edgesEnd(); e_iter != e_end; e_iter++ ) { GEdge *e = static_cast<GEdge *>( e_iter.edge()); if ( isEdgeInSector( e) && areNotEqP( e, edge)) { NodeItem *p_item = static_cast<GNode *>( e_iter.node())->item(); QPointF point = node()->item()->mapFromItem( p_item, p_item->boundingRect().center()); if ( isPointInDir( point, edge_point, dir)) { qreal delta = deltaInDir( point, edge_point, dir); if ( isNullP( res) || delta < min_delta) // for selection of closest edge { res = e; min_delta = delta; } } } } return res; }
void updateCache() { if (!dirty) return; dirty = false; if (node->style()->shape() != shape->type()) { delete shape; shape = createShape(node->style()->shape(), q); } shapePath = shape->shape(); outlinePath = shape->outline(); q->setRotation(node->style()->rotation()); q->update(); }
void RootPanel::updateUnit(NavUnit *unit) { NodeItem *el = 0; nodeMap.find(unit->getID(), el); UnitLocation loc = unit->getLocation(); //width is incl. borders and text, so correct for this . loc.x_ = (long)loc.x_ % (navview->width() - 40); loc.y_ = (long)loc.y_ % (navview->height() - 80); el->moveBy(loc.x_ - el->pos().x() , loc.y_ - el->pos().y()); el->show(); canvas.update(); if(unit->getID() == 1) { this->details->updateLocation(loc); } }
koregui::NodeItem* koregui::SceneViewer ::createNode(kore::SceneNode* sourcenode, int x, int y) { NodeItem* nodeItem = new NodeItem(sourcenode); _scene.addItem(nodeItem); std::vector<kore::SceneNodePtr> pnode = sourcenode->getChildren(); int startx = x -(estimateTreeWidth(sourcenode)/2); for (unsigned int i = 0; i<pnode.size(); i++) { int localwidth = estimateTreeWidth(pnode[i].get()); NodePathItem* path = new NodePathItem(nodeItem, createNode(pnode[i].get(), startx + localwidth/2, y + nodeItem->getHeight() + 80)); path->setZValue(-1); _scene.addItem(path); startx += localwidth; } nodeItem->setPos(x, y); return nodeItem; }
void GraphEditor::mouseMoveEvent(QMouseEvent* e) {if(gwp->moving_item) {//setRenderHints(!QPainter::Antialiasing); gwp->moving_item->moveBy(e->pos().x() - start_position.x(), e->pos().y() - start_position.y()); start_position = e->pos(); } else if(gwp->moving_subgraph) {setRenderHints(0); GeometricGraph & G = *(gwp->pGG); Prop<NodeItem *> nodeitem(G.Set(tvertex()),PROP_CANVAS_ITEM); short vcol=0; G.vcolor.getinit(vcol); NodeItem * node; for(tvertex v = 1; v <= G.nv();v++) {node =(NodeItem *)nodeitem[v]; if(G.vcolor[node->v] != vcol)continue; node->moveBy(e->pos().x() - start_position.x(), e->pos().y() - start_position.y()); } start_position = e->pos(); } else if(gwp->curs_item) // moving the elastic cursor gwp->curs_item->setToPoint(e->pos().x(),e->pos().y()); }
bool GraphScene::saveTo(const QString &fileName) { QFile file(fileName); if (file.open(QFile::WriteOnly | QFile::Truncate)) { QTextStream stream(&file); // Save the nodes with the following line format: 'node $NAME $TYPE $ROW $COL $FORMULA' for (int row = 0; row < m_gridLayout->rowCount(); row++) { for (int column = 0; column < m_gridLayout->columnCount(); column++) { NodeItem *node = static_cast<NodeItem *>(m_gridLayout->itemAt(row, column)); if (node) { stream << "node " << node->name() << ' ' << node->nodeType() << ' ' << row << ' ' << column << " \"" << node->formula() << '"' << endl; } } } // Save the edges with the following line format: 'edge $NAME $START $END $FORMULA' foreach (const DirectedEdgeItem *edge, m_edges) { stream << "edge " << edge->name() << ' ' << edge->start()->name() << ' ' << edge->end()->name() << " \"" << edge->formula() << '"' << endl; } file.close(); return true; }
void RxDev::on_pushButton_managerNodelet_clicked() { NodeItem * newNode; newNode = new NodeItem("","nodelet",QStringList(),QStringList(),QStringList(),QStringList()); newNode->setType("nodelet"); newNode->setArgs("manager"); newNode->setLocation(findSpace(QPoint(0,55))); newNode->setColor(Qt::yellow); newNode->setPos(findSpace(QPoint(0,55))); if (newNode->getNodeData()==true){ scene->addItem(newNode); } }
void RxDev::on_pushButton_blankNode_clicked() { NodeItem * newNode; newNode = new NodeItem("","",QStringList(),QStringList(),QStringList(),QStringList()); newNode->setType("_blank_node"); newNode->setLocation(findSpace(QPoint(0,55))); newNode->setColor(Qt::yellow); newNode->setPos(findSpace(QPoint(0,55))); if (newNode->getNodeData()==true){ scene->addItem(newNode); } }
void GraphEditor::mousePressEvent(QMouseEvent* e) {GeometricGraph & G = *(gwp->pGG); QPoint p((int)e->pos().x(),(int)e->pos().y()); setFocus(); // as we might loose the focus ColorItem *coloritem; if(FindItem(p,coloritem) != 0) {if(e->button() == Qt::LeftButton) {if(coloritem->node) {gwp->NodeColorItem[color_node]->SetPenColor(White); coloritem->SetPenColor(coloritem->brush_color); color_node = coloritem->brush_color; G.vcolor.definit(color_node); } else {gwp->EdgeColorItem[color_edge]->SetPenColor(White); coloritem->SetPenColor(coloritem->brush_color); color_edge = coloritem->brush_color; G.ecolor.definit(color_edge); } return; } else if(e->button() == Qt::RightButton) {QString t; if(coloritem->node) t.sprintf("Vertex color:%s",ColorName[coloritem->brush_color]); else t.sprintf("Edge color:%s",ColorName[coloritem->brush_color]); gwp->info_item = CreateInfoItem(gwp,t,p); setCursor(QCursor(Qt::WhatsThisCursor)); return; } } ThickItem *thickitem; if(FindItem(p,thickitem) != 0) {if(e->button() == Qt::LeftButton) {gwp->EdgeThickItem[width_edge]->SetBrushColor(White); thickitem->SetBrushColor(Yellow); width_edge = thickitem->width; G.ewidth.definit(width_edge); return; } else if(e->button() == Qt::RightButton) {QString t; t.sprintf("Edge width:%d",thickitem->width); gwp->info_item = CreateInfoItem(gwp,t,p); setCursor(QCursor(Qt::WhatsThisCursor)); return; } } if(e->button() == Qt::RightButton ) {NodeItem* node; EdgeItem *edge; QString t; int rtt = FindItem(p,node,edge); if(rtt == 0)rtt = FindItem(p,edge);//augment the collision zone if(rtt == node_rtti) if (G.Set().exist(PROP_VSLABEL) && G.Set(tvertex()).exist(PROP_SLABEL)) {QString tt; Prop1<svector<tstring *> >vslabel(G.Set(),PROP_VSLABEL); Prop<int> slabel(G.Set(tvertex()),PROP_SLABEL,0); if (vslabel()[slabel[node->v]]==(tstring *)0) tt="(null)"; else tt=~(*(vslabel()[slabel[node->v]])); t.sprintf("vertex:%d Label:%d (%s)",(node->v)(),G.vlabel[node->v],(const char *)tt.toLatin1()); } else t.sprintf("vertex:%d Label:%d",(node->v)(),G.vlabel[node->v]); else if(rtt == edge_rtti) {double d = Distance(G.vcoord[G.vin[edge->e]],G.vcoord[G.vin[-(edge->e)]])+.5; t.sprintf("edge:%d Label:%d len:%d",(edge->e)(),G.elabel[edge->e],(int)d); } else {t.sprintf("(%d,%d)",(int)e->pos().x(),(int)e->pos().y()); setCursor(QCursor(Qt::BlankCursor)); } gwp->info_item = CreateInfoItem(gwp,t,p); return; } //GetMouseAction_1 returns the active radio button (0,5) int MouseAction = GetMouseAction_1(); bool Shift = e->modifiers() == Qt::ShiftModifier; bool Control = e->modifiers() == Qt::ControlModifier; bool SControl = e->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier); if(e->button() == Qt::MidButton) //move MouseAction = (Shift) ? -3 : 3; else if(Shift && MouseAction == 1) //add MouseAction = -1; // delete vertex or edge else if(Control && MouseAction == 1) MouseAction = 10; //duplicate graph else if(SControl && MouseAction == 1) MouseAction = 11; //duplicate + else if(Shift && MouseAction == 2) //Orient or reorient if oriented MouseAction = -2; //disorient else if(Shift && MouseAction == 3) //move vertices MouseAction = -3; //move colored vertices else if(Shift && MouseAction == 4) //bissect MouseAction = -4; //contract else if(Shift && MouseAction == 5) //define exterior face MouseAction = -5; //define extbrin else if(Shift && MouseAction == 6) //define a label MouseAction = -6; //reset all labels to indices if(MouseAction == 0) // color {NodeItem* node; EdgeItem *edge; int rtt = FindItem(p,node,edge); if(rtt == 0) //augment the collision zone {rtt = FindItem(p,edge); if(rtt == 0)return; } if(rtt == node_rtti) {mywindow->UndoTouch(false); G.vcolor[node->v] = color_node; node->SetColor(color[color_node]); } else if(rtt == edge_rtti) {mywindow->UndoTouch(false); G.ecolor[edge->e] = color_edge; G.ewidth[edge->e] = width_edge; if(edge->lower) edge->SetColor(color[color_edge]); else edge->opp->SetColor(color[color_edge]); } return; } else if(MouseAction == 1) // Start create an edge {mywindow->UndoTouch(false); Prop<NodeItem *> nodeitem(G.Set(tvertex()),PROP_CANVAS_ITEM); NodeItem* node; EdgeItem *edge; tvertex v; int h = (int)gwp->canvas->height(); int rtt = FindItem(p,node,edge); if(rtt != node_rtti)// add a vertex {Tpoint pp((double)p.x(),(double)(h - p.y())); v = G.NewVertex(pp); ToGrid(v); nodeitem[v] = node = CreateNodeItem(v,gwp); mywindow->mouse_actions->ButtonUndoGrid->setDisabled(true); } else v = node->v; start_position = QPoint((int)G.vcoord[v].x(),h-(int)G.vcoord[v].y()); node->SetColor(Qt::red); gwp->curs_item = new CursItem(v,start_position,gwp); } else if(MouseAction == -1) // Delete {NodeItem* node; EdgeItem *edge; int rtt = FindItem(p,node,edge); if(rtt == 0) //augment the collision zone {rtt = FindItem(p,edge); if(rtt == 0)return; } if(rtt == node_rtti) {mywindow->UndoTouch(true); G.DeleteVertex(node->v); mywindow->mouse_actions->ButtonUndoGrid->setDisabled(true); } else {mywindow->UndoTouch(true); G.DeleteEdge(edge->e); } load(false); mywindow->information();// Informations PrintSizeGrid(); return; } else if(MouseAction == 3) // Start moving a vertex {NodeItem* node; EdgeItem *edge; int rtt = FindItem(p,node,edge); if(rtt != node_rtti)return; mywindow->UndoTouch(false); gwp->moving_item = node; start_position = p; return; } else if(MouseAction == -3) // Start moving a subgraph {mywindow->UndoTouch(false); gwp->moving_subgraph = true; start_position = p; return; } else if(MouseAction == 4) // Bissect an edge {mywindow->UndoTouch(true); if(FitToGrid)//and we are sure that ButtonFitGrid exists mywindow->mouse_actions->ButtonFitGrid->setChecked(false); mywindow->mouse_actions->ButtonUndoGrid->setDisabled(true); EdgeItem *edge; int rtt = FindItem(p,edge); if(rtt != edge_rtti)return; G.BissectEdge(edge->e); DoNormalise = false; load(true); DoNormalise = true; mywindow->information();// Informations return; } else if(MouseAction == -4) // Contract an edge {EdgeItem *edge; int rtt = FindItem(p,edge); if(rtt != edge_rtti)return; mywindow->UndoTouch(true); // provisoire if(edge->lower)G.ReverseEdge(edge->e); // end provisoire G.ContractEdge(edge->e); load(false); mywindow->information();// Informations return; } else if(MouseAction == 5) // Color Exterior face {GeometricGraph & G = *(gwp->pGG); Prop<EdgeItem *> edgeitem(G.Set(tedge()),PROP_CANVAS_ITEM); Tpoint pp((double)p.x(),(double)(gwp->canvas->height()-p.y())); if(G.FindExteriorFace(pp) == 0)return; //ColorExteriorface tedge e; ForAllEdges(e,G)edgeitem[e]->SetColor(color[color_edge]); tbrin b0 = G.extbrin(); tbrin b = b0; do {e = b.GetEdge(); edgeitem[e]->SetColor(color[Red]); } while((b = G.cir[-b]) != b0); if(b0() > 0) edgeitem[b0.GetEdge()]->SetColor(color[Green],false); else edgeitem[b0.GetEdge()]->opp->SetColor(color[Green],false); return; } else if(MouseAction == -5) // Define Extbrin {EdgeItem *edge; int rtt = FindItem(p,edge); if(rtt != edge_rtti)return; Prop<EdgeItem *> edgeitem(G.Set(tedge()),PROP_CANVAS_ITEM); tedge je; ForAllEdges(je,G)edgeitem[je]->SetColor(color[color_edge]); GeometricGraph & G = *(gwp->pGG); je = edge->e; // Prop<NodeItem *> nodeitem(G.Set(tvertex()),PROP_CANVAS_ITEM); // NodeItem *n1 = nodeitem[G.vin[je]]; Tpoint p1(n1->x(),n1->y()); // NodeItem *n2 = nodeitem[G.vin[-je]]; Tpoint p2(n2->x(),n2->y()); // Tpoint pp((double)p.x(),(double)p.y()); // G.extbrin() = (Distance2(pp,p1) < Distance2(pp,p2)) ? je.firsttbrin() : je.secondtbrin(); G.extbrin() = (edge->lower ) ? je.firsttbrin() : je.secondtbrin(); edge->SetColor(color[Green],false); return; } else if(MouseAction == 6) // Modify label {NodeItem* node; EdgeItem *edge; int rtt = FindItem(p,node,edge); if(rtt != node_rtti)return; tvertex v = node->v; bool ok; //int res = QInputDialog::getInteger(this,"Pigale","Enter a number:",(int)G.vlabel[node->v],0,2147483647,1,&ok); int res = QInputDialog::getInt(this,"Pigale","Enter a number:",(int)G.vlabel[node->v],0,2147483647,1,&ok); if(!ok)return; G.vlabel[node->v] = res; QString t = getVertexLabel(G.Container(),v); node->SetText(t); return; } else if(MouseAction == -6) // Reset all labels {Prop<NodeItem *> nodeitem(G.Set(tvertex()),PROP_CANVAS_ITEM); for(tvertex v = 1; v <= G.nv();v++) {G.vlabel[v] = v(); nodeitem[v]->SetText(QString("%1").arg(v())); } for(tedge e = 1; e <= G.ne();e++) G.elabel[e] = e(); } else if(MouseAction == 2 || MouseAction == -2) // Orient/Reverse or deorient {Prop<bool> eoriented(G.Set(tedge()),PROP_ORIENTED,false); Prop<bool> reoriented(G.Set(tedge()),PROP_REORIENTED); Prop<EdgeItem *> edgeitem(G.Set(tedge()),PROP_CANVAS_ITEM); mywindow->setShowOrientation(true); EdgeItem *edge; int rtt = FindItem(p,edge); if(rtt != edge_rtti)return; mywindow->UndoTouch(true); if(MouseAction == 2) {if(eoriented[edge->e]) {G.ReverseEdge(edge->e); eoriented[edge->e] = true; reoriented[edge->e] = false; edgeitem[edge->e] = CreateEdgeItem(edge->e,gwp); if(edge->arrow) scene()->removeItem(edge->arrow); else scene()->removeItem(edge->opp->arrow); scene()->removeItem(edge->opp);scene()->removeItem(edge); mywindow->information();// Informations return; } else {eoriented[edge->e] = true; if(edge->lower) {G.ReverseEdge(edge->e);reoriented[edge->e] = false;} edgeitem[edge->e] = CreateEdgeItem(edge->e,gwp); if(edge->arrow) scene()->removeItem(edge->arrow); else scene()->removeItem(edge->opp->arrow); scene()->removeItem(edge->opp);scene()->removeItem(edge); mywindow->information();// Informations return; } } else {eoriented[edge->e] = false; edgeitem[edge->e] = CreateEdgeItem(edge->e,gwp); if(edge->arrow) scene()->removeItem(edge->arrow); else scene()->removeItem(edge->opp->arrow); scene()->removeItem(edge->opp);scene()->removeItem(edge); mywindow->information();// Informations return; } } else if(MouseAction == 10)// Duplicate the sugraph of the current color {mywindow->UndoTouch(true); if(FitToGrid)//and we are sure that ButtonFitGrid exists mywindow->mouse_actions->ButtonFitGrid->setChecked(false); mywindow->mouse_actions->ButtonUndoGrid->setDisabled(true); short vcol=0; G.vcolor.getinit(vcol); G.vcolor.definit((short)((vcol+1)%16)); GeometricGraph & G = *(gwp->pGG); Tpoint translate(this->width()/2.,0); int n = G.nv(); svector<tvertex> newvertex(1,n); tvertex v; for(v = 1; v <= n;v++)//translate all the graph G.vcoord[v] /= 2.; for(v = 1; v <= n;v++) {if(G.vcolor[v] != vcol)continue; newvertex[v] = G.NewVertex(G.vcoord[v] + translate); } int m = G.ne(); tvertex v1,v2; for(tedge e = 1; e <= m;e++) {v1 = G.vin[e];v2 = G.vin[-e]; if(G.vcolor[v1] == vcol && G.vcolor[v2] == vcol) G.NewEdge(newvertex[v1],newvertex[v2]); } load(true); mywindow->information();// Informations } else if(MouseAction == 11) //Duplicate the sugraph of the current color // and add edges between a new vertex and its father {mywindow->UndoTouch(true); if(FitToGrid)//and we are sure that ButtonFitGrid exists mywindow->mouse_actions->ButtonFitGrid->setChecked(false); mywindow->mouse_actions->ButtonUndoGrid->setDisabled(true); mywindow->mouse_actions->ButtonFitGrid->setChecked(false); short vcol=0; G.vcolor.getinit(vcol); G.vcolor.definit((short)((vcol+1)%16)); GeometricGraph & G = *(gwp->pGG); Tpoint translate(this->width()/2.,0); int n = G.nv(); svector<tvertex> newvertex(1,n); tvertex v; for(v = 1; v <= n;v++)//translate all the graph G.vcoord[v] /= 2.; for(v = 1; v <= n;v++) {if(G.vcolor[v] != vcol)continue; newvertex[v] = G.NewVertex(G.vcoord[v] + translate); } int m = G.ne(); tvertex v1,v2; for(tedge e = 1; e <= m;e++) {v1 = G.vin[e];v2 = G.vin[-e]; if(G.vcolor[v1] == vcol && G.vcolor[v2] == vcol) G.NewEdge(newvertex[v1],newvertex[v2]); } for(v = 1; v <= n;v++) {if(G.vcolor[v] != vcol)continue; G.NewEdge(v,newvertex[v]); } load(true); mywindow->information();// Informations } }
void GraphEditor::mouseReleaseEvent(QMouseEvent* event) {//setRenderHints(QPainter::Antialiasing); if(gwp->info_item) //end info {scene()->removeItem(gwp->info_item->rectitem); scene()->removeItem(gwp->info_item); gwp->info_item = 0; setCursor(QCursor(Qt::ArrowCursor)); return; } if(gwp->moving_item) //end moving a vertex {if(!FitToGrid) {gwp->moving_item = 0;return;} GeometricGraph & G = *(gwp->pGG); NodeItem *node = gwp->moving_item; tvertex v = node->v; double prev_x = G.vcoord[v].x(); double prev_y = G.vcoord[v].y(); ToGrid(v); double dx = G.vcoord[v].x() - prev_x; double dy = G.vcoord[v].y() - prev_y; G.vcoord[v].x() = prev_x; G.vcoord[v].y() = prev_y; node->moveBy(dx,-dy); gwp->moving_item = 0; UpdateSizeGrid(); PrintSizeGrid(); return; } if(gwp->moving_subgraph == true) {gwp->moving_subgraph = false; if(!FitToGrid)return; GeometricGraph & G = *(gwp->pGG); Prop<NodeItem *> nodeitem(G.Set(tvertex()),PROP_CANVAS_ITEM); short vcol=0; G.vcolor.getinit(vcol); NodeItem * node; // Find a vertex of the subgraph tvertex mv = 0; tvertex v; for(v = 1; v <= G.nv();v++) {node =(NodeItem *)nodeitem[v]; if(G.vcolor[node->v] != vcol)continue; else {mv = v;break;} } if(!mv)return; double prev_x = G.vcoord[mv].x(); double prev_y = G.vcoord[mv].y(); ToGrid(mv); double dx = G.vcoord[mv].x() - prev_x; double dy = G.vcoord[mv].y() - prev_y; G.vcoord[mv].x() = prev_x; G.vcoord[mv].y() = prev_y; for(v = 1;v <= G.nv();v++) {node =(NodeItem *)nodeitem[v]; if(G.vcolor[node->v] != vcol)continue; node->moveBy(dx,-dy); } UpdateSizeGrid(); PrintSizeGrid(); return; } if(gwp->curs_item)// end creating an edge {GeometricGraph & G = *(gwp->pGG); Prop<EdgeItem *> edgeitem(G.Set(tedge()),PROP_CANVAS_ITEM); Prop<NodeItem *> nodeitem(G.Set(tvertex()),PROP_CANVAS_ITEM); NodeItem* node; EdgeItem *edge; tvertex v1,v2; // Reset the color of starting vertex v1 = gwp->curs_item->v; node = (NodeItem *)(nodeitem[v1]); node->SetColor(color[G.vcolor[v1]]); QPoint p(event->pos()); ToGrid(p); int rtt = FindItem(p,node,edge); v2 = (rtt != node_rtti) ? 0 : node->v; if(rtt != node_rtti) //create a vertex {int h = (int)gwp->canvas->height(); Tpoint pp((double)p.x(),(double)(h - p.y())); v2 = G.NewVertex(pp);ToGrid(v2); nodeitem[v2] = CreateNodeItem(v2,gwp); mywindow->mouse_actions->ButtonUndoGrid->setDisabled(true); if(IsGrid)UpdateSizeGrid(); } else v2 = node->v; if(v1 != v2) // Create an edge {tedge e = G.NewEdge(v1,v2); edgeitem[e] = CreateEdgeItem(e,gwp); } delete gwp->curs_item; gwp->curs_item = 0; mywindow->information();// Informations if(v1 == v2) // We have created a vertex PrintSizeGrid(); return; } }
void Main::addMesh() { int x0 = 0; int y0 = 0; if ( !tb ) tb = new QBrush( Qt::red ); if ( !tp ) tp = new QPen( Qt::black ); int nodecount = 0; int w = int(canvas.width()); int h = int(canvas.height()); const int dist = 30; int rows = h / dist; int cols = w / dist; #ifndef QT_NO_PROGRESSDIALOG Q3ProgressDialog progress( "Creating mesh...", "Abort", rows, this, "progress", TRUE ); #endif canvas.update(); Q3MemArray<NodeItem*> lastRow(cols); for ( int j = 0; j < rows; j++ ) { int n = j%2 ? cols-1 : cols; NodeItem *prev = 0; for ( int i = 0; i < n; i++ ) { NodeItem *el = new NodeItem; canvas.addItem(el); nodecount++; int r = qrand(); int xrand = r %20; int yrand = (r/20) %20; el->setPos( xrand + x0 + i*dist + (j%2 ? dist/2 : 0 ), yrand + y0 + j*dist ); if ( j > 0 ) { if ( i < cols-1 ) canvas.addItem(new EdgeItem( lastRow[i], el)); if ( j%2 ) canvas.addItem(new EdgeItem( lastRow[i+1], el)); else if ( i > 0 ) canvas.addItem(new EdgeItem( lastRow[i-1], el)); } if ( prev ) { canvas.addItem(new EdgeItem( prev, el)); } if ( i > 0 ) lastRow[i-1] = prev; prev = el; } lastRow[n-1]=prev; #ifndef QT_NO_PROGRESSDIALOG progress.setProgress( j ); if ( progress.wasCancelled() ) break; #endif } #ifndef QT_NO_PROGRESSDIALOG progress.setProgress( rows ); #endif // qDebug( "%d nodes, %d edges", nodecount, EdgeItem::count() ); }
bool GraphScene::loadFrom(const QString &fileName) { QFile file(fileName); if (file.exists() && file.open(QFile::ReadOnly)) { QTextStream stream(&file); QHash<QString, NodeItem *> nodes; // Temporary hashmap for faster lookup init(EmptyInit); // Create an empty scene QString line; do { // Iterate over all the lines in the file line = stream.readLine(); // and split the line at ' ' characters const QStringList splittedLine = line.split(" "); if (splittedLine[0] == "node") { // Found a node, add it to the scene NodeItem *node = new NodeItem(NULL, this); node->setName(splittedLine[1]); NodeItem::NodeType nodeType = static_cast<NodeItem::NodeType>(splittedLine[2].toInt()); switch (nodeType) { case NodeItem::InputNode: setInputNode(node); // We found the input node break; case NodeItem::OutputNode: setOuputNode(node); // We found the ouput node break; case NodeItem::StandardNode: // This should already be set by default but doesn't harm here node->setNodeType(NodeItem::StandardNode); break; } // There is obviously a (Matlab) formula attached, parse it... if (splittedLine.length() > 5) { int formulaStart = line.indexOf('"'); QString formula = line; formula.remove(0, formulaStart); while (!formula.endsWith('"')) { // Formula spans multiple lines formula += '\n' + stream.readLine(); } formula.chop(1); // Remove leading '"' formula.remove(0, 1); // Remove trailing '"' node->setFormula(formula); } nodes.insert(node->name(), node); m_gridLayout->addItem(node, splittedLine[3].toInt(), splittedLine[4].toInt()); } else if (splittedLine[0] == "edge") { NodeItem *start = nodes[splittedLine[2]]; // Found an edge, add it to the scene NodeItem *end = nodes[splittedLine[3]]; DirectedEdgeItem *edge = addEdge(start, end); edge->setName(splittedLine[1]); // There is obviously a (Matlab) formula attached, parse it... if (splittedLine.length() > 4) { int formulaStart = line.indexOf('"'); QString formula = line; formula.remove(0, formulaStart); while (!formula.endsWith('"')) { // Formula spans multiple lines formula += '\n' + stream.readLine(); } formula.chop(1); // Remove leading '"' formula.remove(0, 1); // Remove trailing '"' edge->setFormula(formula); } } } while (!line.isNull()); emit graphChanged(); file.close(); return true; } return false; }
void MainWindow::applySpringLayout() { ConstantValueDoubleMap weights(1.0f); RandomNumberGenerator rng(QDateTime::currentMSecsSinceEpoch()); // Create an undirected copy of the graph QMap<GraphVertex, DigraphVertex> mapDtoU; QMap<DigraphVertex, GraphVertex> mapUtoD; Graph g; { // Copy the nodes std::pair<DigraphVertexIterator, DigraphVertexIterator> digraphVertices = boost::vertices(m_graph); DigraphVertexIterator vit = digraphVertices.first; for (; vit != digraphVertices.second; vit++) { // Add the vertex GraphVertex v = boost::add_vertex(m_graph[*vit], g); // Create the mapping mapDtoU[*vit] = v; mapUtoD[v] = *vit; } // Copy the edges std::pair<Digraph::edge_iterator, Digraph::edge_iterator> digraphEdges = boost::edges(m_graph); Digraph::edge_iterator eit = digraphEdges.first; for (; eit != digraphEdges.second; eit++) { // Get the nodes in terms of the undirected graph DigraphVertex src = boost::source(*eit, m_graph); DigraphVertex tgt = boost::target(*eit, m_graph); // Add an edge into the undirected graph boost::add_edge(mapDtoU[src], mapDtoU[tgt], m_graph[*eit], g); } } // Define the topology to work in QRectF rc(m_graphView->visibleRegion().boundingRect()); float adjH = rc.width() * 0.1f; float adjV = rc.height() * 0.1f; rc.adjust(adjH, adjV, -adjH, -adjV); rc.moveTo(-rc.width() / 2.0f, -rc.height() / 2.0f); Topology top(rng, rc.left(), rc.top(), rc.right(), rc.bottom()); MaxIterationsLayoutTolerance<double> done( boost::num_vertices(m_graph) * m_controlsDock->maxIterations(), m_controlsDock->layoutTolerance()); // Seed with a random layout boost::random_graph_layout(g, get(&NodeProperties::pos, g), top); // Now apply the force-directed layout boost::kamada_kawai_spring_layout(g, get(&NodeProperties::pos, g), weights, top, boost::side_length(rc.width()), done); // Forward the calculated values into the graphics objects std::pair<GraphVertexIterator, GraphVertexIterator> iterators = boost::vertices(g); GraphVertexIterator it = iterators.first; for (; it != iterators.second; ++it) { TopologicalPoint pt = g[*it].pos; NodeItem* node = g[*it].item; // Set the scene item node->setPos(pt[0], pt[1]); // Update the digraph m_graph[mapUtoD[*it]].pos = pt; } }
/*!\brief reimplementation of the mouseReleaseEvent * * ... */ void LaunchFileView::mouseReleaseEvent(QMouseEvent *event) { if (_handScrolling) { _handScrolling = false; viewport()->setCursor(_savedCursor); event->accept(); return; } if (itemAt((event->pos()))){ //else tool crashes if (myMode== DeleteItem && event->button() == Qt::LeftButton) { if (itemAt(event->pos())->type() == NodeItem::Type) { qgraphicsitem_cast<NodeItem *>(itemAt(event->pos()))->removeArrows(); scene()->removeItem(itemAt(event->pos())); ///removes the Node from the scene } else if (itemAt(event->pos())->type() == 8){ // Don't try to kill the View if (itemAt(event->pos())->parentItem()->type() == NodeItem::Type){ qgraphicsitem_cast<NodeItem *>((itemAt(event->pos()))->parentItem())->removeArrows(); scene()->removeItem((itemAt(event->pos()))->parentItem()); ///removes the Node from the scene }else scene()->removeItem((itemAt(event->pos()))->parentItem()); ///removes the Parameter }else if(itemAt(event->pos())->type() == GroupItem::Type) { QList<QGraphicsItem *> list; list=itemAt(event->pos())->childItems(); //qDebug()<<"Begin group items->"; for (int i = 0; i < list.size(); i++) { if (list.at(i)->type() != 8) (list.at(i))->setParentItem(0); // qDebug()<<(list.at(i)->type()); } //qDebug()<<"<-End group items"; scene()->removeItem(itemAt(event->pos())); } event->setAccepted(true);// tell the base class we are handling this event } }if (line != 0 && myMode == InsertLine) { QList<QGraphicsItem *> startItems = scene()->items(line->line().p1()); if (startItems.count() && startItems.first() == line) startItems.removeFirst(); QList<QGraphicsItem *> endItems = scene()->items(line->line().p2()); if (endItems.count() && endItems.first() == line) endItems.removeFirst(); if (startItems.count() &&startItems.first()->type() == 8) startItems.first() = startItems.first()->parentItem(); if (endItems.count() && endItems.first()->type() == 8) endItems.first() = endItems.first()->parentItem(); scene()->removeItem(line); //remove temporary line delete line; //! [11] //! [12] if (startItems.count() > 0 && endItems.count() > 0 && startItems.first()->type() == NodeItem::Type && endItems.first()->type() == NodeItem::Type && startItems.first() != endItems.first()) { NodeItem *startItem = qgraphicsitem_cast<NodeItem *>(startItems.first()); NodeItem *endItem = qgraphicsitem_cast<NodeItem *>(endItems.first()); RemapArrow *arrow = new RemapArrow(startItem, endItem); if (arrow->getArrowData()==true){ startItem->addArrow(arrow); endItem->addArrow(arrow); arrow->setZValue(-20); scene()->addItem(arrow); arrow->updatePosition(); } } } //! [12] //! [13] line = 0; QGraphicsView::mouseReleaseEvent(event); }
int MainWindow::buildNetwork(const QString& description) { int result = Success; // Split into lines QStringList lines = description.split(QRegExp("[\\n|\\r]"), QString::SkipEmptyParts); if (lines.isEmpty()) { postErrorMessage("Problem specification is empty after whitespace " "removed!"); return ErrorEmpty; } // Validate the length of the specification int nodeCount = lines[0].toInt(); postInfoMessage(QString("Expecting %1x%1 adjacency matrix...") .arg(nodeCount)); if (lines.length() != (nodeCount + 2)) { postErrorMessage(QString("Expecting %1 lines in specification; read %2") .arg(nodeCount + 2) .arg(lines.length())); return ErrorSpecTooSmall; } // Clear the existing graph and scene if (boost::num_vertices(m_graph) != 0) { postWarningMessage("Existing network already loaded; must be cleared " "in order to continue."); int response = QMessageBox::question(this, "NetRoute", "There is " "already a graph in the explorer; the current data will have to " "be discared. Continue?"); if (response == QMessageBox::No) { postErrorMessage("Aborted by user."); return WarningAbort; } postInfoMessage("Discarding network."); clearNetwork(); } // Create the nodes postInfoMessage("Creating nodes..."); for (int i = 0; i < nodeCount; ++i) { QString name = QString("%1").arg(QChar('A' + i)); NodeItem* node = new NodeItem; node->setText(name); m_graphNodes[name] = node; boost::add_vertex(NodeProperties(node), m_graph); m_graphScene->addItem(node); } // Create the edges postInfoMessage("Creating edges from adjacency matrix..."); for (int i = 0; i < nodeCount; ++i) { QString line = lines[i + 1].trimmed(); QStringList weights = line.split(',', QString::SkipEmptyParts); // Sanity check if (weights.length() != nodeCount) { postErrorMessage( QString("Matrix row %1 has %2 columns; expecting %3.") .arg(i) .arg(weights.length()) .arg(nodeCount)); return ErrorRowTooShort; } // Actually create the edges postInfoMessage(QString("Creating edges for node %1") .arg(QChar('A' + i))); DigraphVertex vStart = boost::vertex(i, m_graph); for (int j = 0; j < nodeCount; ++j) { bool ok; int weight = weights[j].trimmed().toInt(&ok); if (ok && weight >= 0) { DigraphVertex vEnd = boost::vertex(j, m_graph); // Create the new edge item EdgeItem* edge = new EdgeItem; edge->setStartNode(m_graph[vStart].item); edge->setEndNode(m_graph[vEnd].item); edge->setWeight(weight); m_graphScene->addItem(edge); // Add it to the graph boost::add_edge(vStart, vEnd, EdgeProperties(edge), m_graph); } else if (!ok) { postWarningMessage(QString("Weight (%1,%2) is malformed: %3.") .arg(i) .arg(j) .arg(weights[j])); result |= WarningBadCell; } } } // Parse the final line of the description: the start/end nodes QStringList nodes = lines[lines.length() - 1].split(QRegExp("\\s+"), QString::SkipEmptyParts); if (nodes.length() != 2) { postWarningMessage("Start and end nodes line is malformed; " "routing will not take place."); result |= WarningBadStartEnd; } else { QString startNodeName = nodes[0]; QString endNodeName = nodes[1]; m_routeStart = m_graphNodes[startNodeName]; m_routeEnd = m_graphNodes[endNodeName]; if (!m_routeStart) { postWarningMessage(QString("Failed to find start node '%1'; " "routing will not take place.") .arg(startNodeName)); result |= WarningNoStartNode; } if (!m_routeEnd) { postWarningMessage(QString("Failed to find end node '%1'; " "routing will not take place.") .arg(endNodeName)); result |= WarningNoEndNode; } } // Graph was built successfully, even if some parsing errors arose. return result; }
void MainWindow::routeNetwork() { // Storage class for the metadata required by Dijkstra struct MetaData { int distance; EdgeItem* edge; NodeItem* previous; NodeItem* owner; MetaData() : distance(INT_MAX) , edge(nullptr) , previous(nullptr) , owner(nullptr) { } MetaData(NodeItem* owner_) : distance(INT_MAX) , edge(nullptr) , previous(nullptr) , owner(owner_) { } }; QMap<NodeItem*, MetaData> metadata; QList<NodeItem*> nodes; NodeItem* current; // Initialise data-structres postInfoMessage("Preparing to route..."); { QMapIterator<QString, NodeItem*> i(m_graphNodes); while (i.hasNext()) { auto item = i.next(); // Initialise the metadata MetaData md(item.value()); if (item.value() == m_routeStart) { // Need minimal distance for the start node md.distance = 0; } metadata[i.value()] = md; // Initialise the node list nodes.append(i.value()); } } // Dijkstra's algorithm: calculate all the distances while (!nodes.isEmpty()) { // Find node with smallest distance { int d = INT_MAX; auto elem = nodes.end(); for (auto it = nodes.begin(); it != nodes.end(); ++it) { int thisDistance = metadata[*it].distance; if (thisDistance < d) { d = thisDistance; elem = it; } } current = *elem; // If we hit the target, we can stop if (current == m_routeEnd) { postInfoMessage("Search complete; reached target node!"); break; } else { // Emshrinken the list nodes.erase(elem); } } postInfoMessage(QString("Considering node %1...") .arg(current->text())); // Visit the neighbours QListIterator<EdgeItem*> i(current->edges()); while (i.hasNext()) { EdgeItem* edge = i.next(); NodeItem* neighbour = edge->endNode(); int dist = metadata[current].distance + edge->weight(); if (dist < metadata[neighbour].distance) { metadata[neighbour].distance = dist; metadata[neighbour].edge = edge; metadata[neighbour].previous = current; } } } // Walk backwards from the target to the source, building the path postInfoMessage("Back-tracking to construct route..."); for (current = m_routeEnd; current; current = metadata[current].previous) { EdgeItem* edge = metadata[current].edge; if (edge) { m_route.prepend(edge); } } // All done! postSuccessMessage("Routing complete!"); // Update the display setHighlightStartNode(m_controlsDock->highlightStartNode()); setHighlightEndNode(m_controlsDock->highlightEndNode()); setHighlightPath(m_controlsDock->highlightPath()); }