void UPRSupplier::revertUPR(UpwardPlanRep& upr, GraphAttributes& uga){ upr.delNode(getSource(upr)); upr.delNode(getSink(upr)); upr.delNode(getSink(upr)); node source = getSource(upr); node sink = getSink(upr); vector<edge> edgesToDelete; edge e; forall_edges(e, upr){ if (upr.original(e)->source() == upr.original(source) || upr.original(e)->target() == upr.original(sink)) edgesToDelete.push_back(e); } for (vector<edge>::iterator it = edgesToDelete.begin(); it != edgesToDelete.end(); ++it){ upr.delEdge(*it); } upr.delNode(source); upr.delNode(sink); vector<node> nodesToUnsplit; node n; forall_nodes(n, upr){ if (n->indeg() == 1 && n->outdeg() == 1 && upr.isDummy(n)){ nodesToUnsplit.push_back(n); } } for (vector<node>::iterator it = nodesToUnsplit.begin(); it != nodesToUnsplit.end(); ++it){ edge in = (*it)->firstAdj()->theEdge(); edge out = (*it)->lastAdj()->theEdge(); if (in->source() == *it) swap(in, out); DPolyline& inBends = uga.bends(in); DPolyline& outBends = uga.bends(out); inBends.popBack(); double x = inBends.back().m_x; int counter = 0; for (ListIterator<DPoint> it = outBends.begin(); it != outBends.end(); ++it){ if (counter < 2){ DPoint p(x, (*it).m_y); inBends.pushBack(p); counter++; } else { inBends.pushBack(*it); } } upr.unsplit(in, out); } }
void BendPromotion(Graph& G, GraphAttributes& GA) { List<edge> edges; G.allEdges(edges); while (!edges.empty()) { edge e = edges.popFrontRet(); DPolyline bends_e = GA.bends(e); node s = e->source(); node t = e->target(); //check if an edge has bendpoints if (!bends_e.empty()) { while (!bends_e.empty()) { DPoint p = bends_e.front(); //insert new node node n = G.newNode(); GA.x(n) = p.m_x; GA.y(n) = p.m_y; edge e_ = G.newEdge(s, n); GA.arrowType(e_) = ogdf::EdgeArrow::None; GA.strokeColor(e_) = Color("#bababa"); s = n; bends_e.popFront(); } edge e_ = G.newEdge(s, t); GA.arrowType(e_) = ogdf::EdgeArrow::None; GA.strokeColor(e_) = Color("#bababa"); G.delEdge(e); } } }
double LayoutStatistics::edgeLengths( const GraphAttributes &ga, double *pMinLength, double *pMaxLength, double *pAvgLength, double *pStdDeviation, bool considerSelfLoops) { const Graph &G = ga.constGraph(); int m = G.numberOfEdges(); double totalLength = 0, minLength = numeric_limits<double>::max(), maxLength = -numeric_limits<double>::max(); EdgeArray<double> len(G); int nSelfLoops = 0; for(edge e : G.edges) { if(!considerSelfLoops && e->isSelfLoop()) { nSelfLoops++; continue; } const DPolyline &dpl = ga.bends(e); if(!dpl.empty()) { len[e] = dpl.length(); } else { DPoint pv = DPoint(ga.x(e->source()),ga.y(e->source())); DPoint pw = DPoint(ga.x(e->target()),ga.y(e->target())); len[e] = pv.distance(pw); } totalLength += len[e]; minLength = min(minLength, len[e]); maxLength = max(maxLength, len[e]); } m -= nSelfLoops; double avgEdgeLength = totalLength / m; if(pAvgLength) *pAvgLength = avgEdgeLength; if(pMinLength) *pMinLength = minLength; if(pMaxLength) *pMaxLength = maxLength; if(pStdDeviation) { double sum = 0; for(edge e : G.edges) { if(!considerSelfLoops && e->isSelfLoop()) continue; double d = len[e] - avgEdgeLength; sum += d*d; } *pStdDeviation = sqrt(sum / m); } return totalLength; }
int LayoutStatistics::numberOfBends( const GraphAttributes &ga, int *pMinBendsPerEdge, int *pMaxBendsPerEdge, double *pAvgBendsPerEdge, double *pStdDeviation, bool considerSelfLoops) { const Graph &G = ga.constGraph(); int m = G.numberOfEdges(); int totalBends = 0, minBends = numeric_limits<int>::max(), maxBends = 0; EdgeArray<int> bends(G); int nSelfLoops = 0; for(edge e : G.edges) { if(!considerSelfLoops && e->isSelfLoop()) { nSelfLoops++; continue; } const DPolyline &dpl = ga.bends(e); bends[e] = max(0, dpl.size() - 2); totalBends += bends[e]; minBends = min(minBends, bends[e]); maxBends = max(maxBends, bends[e]); } m -= nSelfLoops; double avgBends = double(totalBends) / m; if(pAvgBendsPerEdge) *pAvgBendsPerEdge = avgBends; if(pMinBendsPerEdge) *pMinBendsPerEdge = minBends; if(pMaxBendsPerEdge) *pMaxBendsPerEdge = maxBends; if(pStdDeviation) { double sum = 0; for(edge e : G.edges) { if(!considerSelfLoops && e->isSelfLoop()) continue; double d = bends[e] - avgBends; sum += d*d; } *pStdDeviation = sqrt(sum / m); } return totalBends; }
void FastMultipoleEmbedder::call(GraphAttributes &GA, const EdgeArray<float>& edgeLength, const NodeArray<float>& nodeSize) { allocate(GA.constGraph().numberOfNodes(), GA.constGraph().numberOfEdges()); m_pGraph->readFrom(GA, edgeLength, nodeSize); run(m_numIterations); m_pGraph->writeTo(GA); deallocate(); for(edge e : GA.constGraph().edges) { GA.bends(e).clear(); } }
static inline void writeAttributes( std::ostream &out, const GraphAttributes &GA, const edge &e) { const long flags = GA.attributes(); out << "["; bool comma = false; // Whether to put comma before attribute. if(flags & GraphAttributes::edgeLabel) { writeAttribute(out, comma, "label", GA.label(e)); } if(flags & GraphAttributes::edgeDoubleWeight) { writeAttribute(out, comma, "weight", GA.doubleWeight(e)); } else if(flags & GraphAttributes::edgeIntWeight) { writeAttribute(out, comma, "weight", GA.intWeight(e)); } if(flags & GraphAttributes::edgeGraphics) { // This should be legal cubic B-Spline in the future. std::stringstream sstream; for(const DPoint &p : GA.bends(e)) { sstream << p.m_x << "," << p.m_y << " "; } writeAttribute(out, comma, "pos", sstream.str()); } if(flags & GraphAttributes::edgeArrow) { writeAttribute(out, comma, "dir", dot::toString(GA.arrowType(e))); } if(flags & GraphAttributes::edgeStyle) { writeAttribute(out, comma, "color", GA.strokeColor(e)); } if(flags & GraphAttributes::edgeType) { writeAttribute(out, comma, "arrowhead", GA.arrowType(e)); // Additionaly, according to IBM UML doc dependency is a dashed edge. if(GA.type(e) == Graph::dependency) { writeAttribute(out, comma, "style", "dashed"); } } // NOTE: Edge subgraphs are not supported. out << "]"; }
void GridLayoutModule::mapGridLayout(const Graph &G, GridLayout &gridLayout, GraphAttributes &AG) { // maximum width of columns and rows double maxWidth = 0; double yMax = 0; for(node v : G.nodes) { Math::updateMax<double>(maxWidth, AG.width(v)); Math::updateMax<double>(maxWidth, AG.height(v)); Math::updateMax<double>(yMax, gridLayout.y(v)); } maxWidth += m_separation; // set position of nodes for(node v : G.nodes) { AG.x(v) = gridLayout.x(v) * maxWidth; AG.y(v) = (yMax - gridLayout.y(v)) * maxWidth; } // transform bend points of edges for(edge e : G.edges) { IPolyline ipl = gridLayout.polyline(e); // Remove superfluous bendpoints node v = e->source(); while(!ipl.empty() && ipl.front() == IPoint(gridLayout.x(v), gridLayout.y(v))) { ipl.popFront(); } v = e->target(); while(!ipl.empty() && ipl.back() == IPoint(gridLayout.x(v), gridLayout.y(v))) { ipl.popBack(); } DPolyline &dpl = AG.bends(e); dpl.clear(); for (const IPoint &ip : ipl) { dpl.pushBack(DPoint(ip.m_x*maxWidth, (yMax-ip.m_y)*maxWidth)); } dpl.normalize(); } }
void FastMultipoleMultilevelEmbedder::call(GraphAttributes &GA) { EdgeArray<float> edgeLengthAuto(GA.constGraph()); computeAutoEdgeLength(GA, edgeLengthAuto); const Graph& t = GA.constGraph(); if (t.numberOfNodes() <= 25) { FastMultipoleEmbedder fme; fme.setNumberOfThreads(this->m_iMaxNumThreads); fme.setRandomize(true); fme.setNumIterations(500); fme.call(GA); return; } run(GA, edgeLengthAuto); for(edge e : GA.constGraph().edges) { GA.bends(e).clear(); } }
// create testGraph to test criteria imlementations void CreateGraph(Graph& G, GraphAttributes& GA) { // add nodes node zero = G.newNode(); node one = G.newNode(); node two = G.newNode(); node three = G.newNode(); node four = G.newNode(); // set node positions GA.x(zero) = 4 * NODE_WIDTH; GA.y(zero) = 0; GA.x(one) = 4 * NODE_WIDTH; GA.y(one) = 4 * NODE_HEIGHT; GA.x(two) = 0; GA.y(two) = 2 * NODE_HEIGHT; GA.x(three) = 4 * NODE_WIDTH; GA.y(three) = 8 * NODE_HEIGHT; GA.x(four) = 0; GA.y(four) = 8 * NODE_HEIGHT; // add edges edge zero_one = G.newEdge(zero, one); edge zero_three = G.newEdge(zero, three); edge zero_four = G.newEdge(zero, four); edge one_two = G.newEdge(one, two); edge one_three = G.newEdge(one, three); edge two_three = G.newEdge(two, three); DPolyline &p = GA.bends(zero_three); p.pushBack(DPoint(6 * NODE_WIDTH, 2 * NODE_HEIGHT)); p.pushBack(DPoint(6 * NODE_WIDTH, 6 * NODE_HEIGHT)); }
static void write_ogml_layout_nodes_edges(const GraphAttributes &A, ostream &os) { const Graph &G = A.constGraph(); if (A.has(GraphAttributes::nodeGraphics | GraphAttributes::nodeStyle)) { for(node v : G.nodes) { GraphIO::indent(os,4) << "<nodeStyle idRef=\"n" << v->index() << "\">\n"; if(A.has(GraphAttributes::nodeGraphics)) { GraphIO::indent(os,5) << "<location x=\"" << A.x(v)-0.5*A.width(v) << "\" y=\""<< A.y(v)-0.5*A.height(v) << "\" />\n"; GraphIO::indent(os,5) << "<shape type=\""; switch (A.shape(v)) { case shRect: os << "rect"; break; case shRoundedRect: os << "roundedRect"; break; case shEllipse: os << "ellipse"; break; case shTriangle: os << "triangle"; break; case shPentagon: os << "pentagon"; break; case shHexagon: os << "hexagon"; break; case shOctagon: os << "octagon"; break; case shRhomb: os << "rhomb"; break; case shTrapeze: os << "trapeze"; break; case shParallelogram: os << "parallelogram"; break; case shInvTriangle: os << "invTriangle"; break; case shInvTrapeze: os << "invTrapeze"; break; case shInvParallelogram: os << "invParallelogram"; break; case shImage: os << "image"; break; } os << "\" width=\"" << A.width(v) << "\" height=\"" << A.height(v) << "\" />\n"; } if(A.has(GraphAttributes::nodeStyle)) { // fill-tag GraphIO::indent(os,5) << "<fill"; // color-attribute of fill-tag os << " color=\"" << A.fillColor(v) << "\""; // pattern- and patternColor-attribute of fill-tag (closing) os << " pattern=\"" << fillPatternToOGML(A.fillPattern(v)) << "\" patternColor=\"" << A.fillBgColor(v) << "\" />\n"; // line-tag GraphIO::indent(os,5) << "<line type=\"" << edgeStyleToOGML(A.strokeType(v)) << "\" width=\"" << A.strokeWidth(v) << "\"" << " color=\"" << A.strokeColor(v) << "\""; // closing fill-tag os << " />\n"; } GraphIO::indent(os,4) << "</nodeStyle>\n"; } } if (A.has(GraphAttributes::edgeGraphics | GraphAttributes::edgeStyle)) { int pointId = 0; for(edge e : G.edges) { GraphIO::indent(os,4) << "<edgeStyle idRef=\"e" << e->index() << "\">\n"; if(A.has(GraphAttributes::edgeStyle)) { GraphIO::indent(os,5) << "<line "; if (A.has(GraphAttributes::edgeStyle)) { os << "type=\"" << edgeStyleToOGML(A.strokeType(e)) << "\" width=\"" << A.strokeWidth(e) << "\" "; os << "color=\"" << A.strokeColor(e) << "\" />\n"; } else { os << " />\n"; } } // TODO review the handling of edge arrows if(A.has(GraphAttributes::edgeArrow)) { switch(A.arrowType(e)) { case eaNone: GraphIO::indent(os,5) << "<sourceStyle type=\"none\" color=\"#000000\" size=\"1\" />\n"; GraphIO::indent(os,5) << "<targetStyle type=\"none\" color=\"#000000\" size=\"1\" />\n"; break; case eaLast: GraphIO::indent(os,5) << "<sourceStyle type=\"none\" color=\"#000000\" size=\"1\" />\n"; GraphIO::indent(os,5) << "<targetStyle type=\"arrow\" color=\"#000000\" size=\"1\" />\n"; break; case eaFirst: GraphIO::indent(os,5) << "<sourceStyle type=\"arrow\" color=\"#000000\" size=\"1\" />\n"; GraphIO::indent(os,5) << "<targetStyle type=\"none\" color=\"#000000\" size=\"1\" />\n"; break; case eaBoth: GraphIO::indent(os,5) << "<sourceStyle type=\"arrow\" color=\"#000000\" size=\"1\" />\n"; GraphIO::indent(os,5) << "<targetStyle type=\"arrow\" color=\"#000000\" size=\"1\" />\n"; break; case eaUndefined: // do nothing break; default: // do nothing break; } } // handling of points // TODO: Revise for new OGML specification const DPolyline &dpl = A.bends(e); if (!dpl.empty()) { // handle source node v = e->source(); if(dpl.front().m_x < A.x(v) - A.width(v)/2 || dpl.front().m_x > A.x(v) + A.width(v)/2 || dpl.front().m_y < A.y(v) - A.height(v)/2 || dpl.front().m_y > A.y(v) + A.height(v)/2) { GraphIO::indent(os,5) << "<point id=\"p" << pointId++ << "\" x=\"" << A.x(e->source()) << "\" y=\"" << A.y(e->source()) << "\" />\n"; } // handle points for(const DPoint &dp : dpl) { GraphIO::indent(os,5) << "<point id=\"p" << pointId++ << "\" x=\"" << dp.m_x << "\" y=\"" << dp.m_y << "\" />\n"; } // handle target v = e->target(); if(dpl.back().m_x < A.x(v) - A.width(v)/2 || dpl.back().m_x > A.x(v) + A.width(v)/2 || dpl.back().m_y < A.y(v) - A.height(v)/2 || dpl.back().m_y > A.y(v) + A.height(v)/2) { GraphIO::indent(os,5) << "<point id=\"p" << pointId++ << "\" x=\"" << A.x(e->target()) << "\" y=\"" << A.y(e->target()) << "\" />\n"; } } GraphIO::indent(os,4) << "</edgeStyle>\n"; } } }
void EdgeLengthCompacter::assignCoordinates(const Graph& g, NodeArray<int>& nodeColumns, EdgeArray<int>& edgeColumns, NodeArray<NodeCoordinates>& nodeCoordinates, EdgeArray<EdgeCoordinates>& edgeCoordinates, GraphAttributes& retVal){ assignXCoordinates(nodeColumns, retVal); node n; forall_nodes(n, g){ retVal.y(n) = (nodeCoordinates[n].y_top + nodeCoordinates[n].y_bottom) / 2; } edge e; forall_edges(e, g){ EdgeCoordinates& ec = edgeCoordinates[e]; // cout << "Edge "<< e->source() << " -> " << e->target() << endl; // cout << "\ty1\t"<< ec.y_1<< endl; // cout << "\ty2\t"<< ec.y_2<< endl; // cout << "\tt off\t"<< ec.x_offset_target<< endl; // cout << "\ts_off\t"<< ec.x_offset_source<< endl; node source = e->source(); node target = e->target(); double sourceColumn = nodeColumns[source]; double edgeColumn = edgeColumns[e]; double targetColumn = nodeColumns[target]; double sourceX = sourceColumn * (boxWidth + boxBoxSpacing) + ec.x_offset_source; double targetX = targetColumn * (boxWidth + boxBoxSpacing) + ec.x_offset_target; double edgeX = edgeColumns[e] * (boxWidth + boxBoxSpacing); retVal.bends(e).clear(); DPoint p0(sourceX, nodeCoordinates[source].y_bottom + 0.001); retVal.bends(e).pushBack(p0); DPoint p1(sourceX, ec.y_1); retVal.bends(e).pushBack(p1); if (sourceColumn == edgeColumns[e]){ DPoint p2(sourceX, ec.y_1); retVal.bends(e).pushBack(p2); DPoint p3(sourceX, ec.y_2); retVal.bends(e).pushBack(p3); } else if (targetColumn == edgeColumns[e]){ DPoint p2(targetX, ec.y_1); retVal.bends(e).pushBack(p2); DPoint p3(targetX, ec.y_2); retVal.bends(e).pushBack(p3); } else { DPoint p2(edgeX, ec.y_1); retVal.bends(e).pushBack(p2); DPoint p3(edgeX, ec.y_2); retVal.bends(e).pushBack(p3); } DPoint p4(targetX, ec.y_2); retVal.bends(e).pushBack(p4); DPoint p5(targetX, nodeCoordinates[target].y_top - 0.001); retVal.bends(e).pushBack(p5); }
//************************************************************* // returns GraphAttributes associated with basic graph i // void SimDraw::getBasicGraphAttributes(int i, GraphAttributes &GA, Graph &G) { G = m_G; GA.init(G,m_GA.attributes()); List<edge> LE; m_G.allEdges(LE); forall_listiterators(edge,it,LE) if(m_GA.inSubGraph(*it,i)) { node v; forall_nodes(v,G) { if(compare(GA,v,m_GA,(*it)->source())) { if(m_GA.attributes() & GraphAttributes::nodeGraphics) { GA.x(v) = m_GA.x((*it)->source()); GA.y(v) = m_GA.y((*it)->source()); GA.height(v) = m_GA.height((*it)->source()); GA.width(v) = m_GA.width((*it)->source()); } if(m_GA.attributes() & GraphAttributes::nodeId) GA.idNode(v) = m_GA.idNode((*it)->source()); if(m_GA.attributes() & GraphAttributes::nodeLabel) GA.labelNode(v) = m_GA.labelNode((*it)->source()); } if(compare(GA,v,m_GA,(*it)->target())) { if(m_GA.attributes() & GraphAttributes::nodeGraphics) { GA.x(v) = m_GA.x((*it)->target()); GA.y(v) = m_GA.y((*it)->target()); GA.height(v) = m_GA.height((*it)->target()); GA.width(v) = m_GA.width((*it)->target()); } if(m_GA.attributes() & GraphAttributes::nodeId) GA.idNode(v) = m_GA.idNode((*it)->target()); if(m_GA.attributes() & GraphAttributes::nodeLabel) GA.labelNode(v) = m_GA.labelNode((*it)->target()); } } edge e; forall_edges(e,G) { if(compare(GA,e->source(),m_GA,(*it)->source()) && compare(GA,e->target(),m_GA,(*it)->target())) { if(m_GA.attributes() & GraphAttributes::edgeIntWeight) GA.intWeight(e) = m_GA.intWeight(*it); if(m_GA.attributes() & GraphAttributes::edgeLabel) GA.labelEdge(e) = m_GA.labelEdge(*it); if(m_GA.attributes() & GraphAttributes::edgeColor) GA.colorEdge(e) = m_GA.colorEdge(*it); if(m_GA.attributes() & GraphAttributes::edgeGraphics) GA.bends(e) = m_GA.bends(*it); } } }
bool GmlParser::read(Graph &G, GraphAttributes &AG) { OGDF_ASSERT(&G == &(AG.constGraph())) G.clear(); int minId = m_mapToNode.low(); int maxId = m_mapToNode.high(); int notDefined = minId-1; //indicates not defined id key HashArray<string,Shape> strToShape(shRect); strToShape["rectangle"] = shRect; strToShape["rect"] = shRect; strToShape["roundedRect"] = shRoundedRect; strToShape["oval"] = shEllipse; strToShape["ellipse"] = shEllipse; strToShape["triangle"] = shTriangle; strToShape["pentagon"] = shPentagon; strToShape["hexagon"] = shHexagon; strToShape["octagon"] = shOctagon; strToShape["rhomb"] = shRhomb; strToShape["trapeze"] = shTrapeze; strToShape["parallelogram"] = shParallelogram; strToShape["invTriangle"] = shInvTriangle; strToShape["invTrapeze"] = shInvTrapeze; strToShape["invParallelogram"] = shInvParallelogram; strToShape["image"] = shImage; DPolyline bends; GmlObject *son = m_graphObject->m_pFirstSon; for(; son; son = son->m_pBrother) { switch(id(son)) { case nodePredefKey: { if (son->m_valueType != gmlListBegin) break; // set attributes to default values int vId = notDefined; double x = 0, y = 0, w = 0, h = 0; string label; string templ; string fill; // the fill color attribute string line; // the line color attribute string shape; //the shape type float lineWidth = 1.0f; //node line width int pattern = 1; //node brush pattern int stipple = 1; //line style pattern int weight = 0; // node weight // read all relevant attributes GmlObject *nodeSon = son->m_pFirstSon; for(; nodeSon; nodeSon = nodeSon->m_pBrother) { switch(id(nodeSon)) { case idPredefKey: if(nodeSon->m_valueType != gmlIntValue) break; vId = nodeSon->m_intValue; break; case graphicsPredefKey: { if (nodeSon->m_valueType != gmlListBegin) break; GmlObject *graphicsObject = nodeSon->m_pFirstSon; for(; graphicsObject; graphicsObject = graphicsObject->m_pBrother) { switch(id(graphicsObject)) { case xPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; x = graphicsObject->m_doubleValue; break; case yPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; y = graphicsObject->m_doubleValue; break; case wPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; w = graphicsObject->m_doubleValue; break; case hPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; h = graphicsObject->m_doubleValue; break; case fillPredefKey: if(graphicsObject->m_valueType != gmlStringValue) break; fill = graphicsObject->m_stringValue; break; case linePredefKey: if(graphicsObject->m_valueType != gmlStringValue) break; line = graphicsObject->m_stringValue; break; case lineWidthPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; lineWidth = (float)graphicsObject->m_doubleValue; break; case typePredefKey: if(graphicsObject->m_valueType != gmlStringValue) break; shape = graphicsObject->m_stringValue; break; case patternPredefKey: //fill style if(graphicsObject->m_valueType != gmlIntValue) break; pattern = graphicsObject->m_intValue; case stipplePredefKey: //line style if(graphicsObject->m_valueType != gmlIntValue) break; stipple = graphicsObject->m_intValue; } } break; } case templatePredefKey: if (nodeSon->m_valueType != gmlStringValue) break; templ = nodeSon->m_stringValue; break; case labelPredefKey: if (nodeSon->m_valueType != gmlStringValue) break; label = nodeSon->m_stringValue; break; case edgeWeightPredefKey: //sic! if (nodeSon->m_valueType != gmlIntValue) break; weight = nodeSon->m_intValue; break; } } // check if everything required is defined correctly if (vId == notDefined) { setError("node id not defined"); return false; } // create new node if necessary and assign attributes if (m_mapToNode[vId] == nullptr) m_mapToNode[vId] = G.newNode(); node v = m_mapToNode[vId]; if (AG.attributes() & GraphAttributes::nodeGraphics) { AG.x(v) = x; AG.y(v) = y; AG.width (v) = w; AG.height(v) = h; AG.shape(v) = strToShape[shape]; } if (AG.attributes() & GraphAttributes::nodeLabel) AG.label(m_mapToNode[vId]) = label; if (AG.attributes() & GraphAttributes::nodeTemplate) AG.templateNode(m_mapToNode[vId]) = templ; if (AG.attributes() & GraphAttributes::nodeId) AG.idNode(m_mapToNode[vId]) = vId; if (AG.attributes() & GraphAttributes::nodeWeight) AG.weight(m_mapToNode[vId]) = weight; if (AG.attributes() & GraphAttributes::nodeStyle) { AG.fillColor(m_mapToNode[vId]) = fill; AG.strokeColor(m_mapToNode[vId]) = line; AG.setFillPattern(m_mapToNode[vId], intToFillPattern(pattern)); AG.setStrokeType(m_mapToNode[vId], intToStrokeType(stipple)); AG.strokeWidth(m_mapToNode[vId]) = lineWidth; } }//node //Todo: line style set stipple value break; case edgePredefKey: { string arrow; // the arrow type attribute string fill; //the color fill attribute int stipple = 1; //the line style float lineWidth = 1.0f; double edgeWeight = 1.0; int subGraph = 0; //edgeSubGraphs attribute string label; // label attribute if (son->m_valueType != gmlListBegin) break; // set attributes to default values int sourceId = notDefined, targetId = notDefined; Graph::EdgeType umlType = Graph::association; // read all relevant attributes GmlObject *edgeSon = son->m_pFirstSon; for(; edgeSon; edgeSon = edgeSon->m_pBrother) { switch(id(edgeSon)) { case sourcePredefKey: if (edgeSon->m_valueType != gmlIntValue) break; sourceId = edgeSon->m_intValue; break; case targetPredefKey: if (edgeSon->m_valueType != gmlIntValue) break; targetId = edgeSon->m_intValue; break; case subGraphPredefKey: if (edgeSon->m_valueType != gmlIntValue) break; subGraph = edgeSon->m_intValue; break; case labelPredefKey: if (edgeSon->m_valueType != gmlStringValue) break; label = edgeSon->m_stringValue; break; case graphicsPredefKey: { if (edgeSon->m_valueType != gmlListBegin) break; GmlObject *graphicsObject = edgeSon->m_pFirstSon; for(; graphicsObject; graphicsObject = graphicsObject->m_pBrother) { if(id(graphicsObject) == LinePredefKey && graphicsObject->m_valueType == gmlListBegin) { readLineAttribute(graphicsObject->m_pFirstSon,bends); } if(id(graphicsObject) == arrowPredefKey && graphicsObject->m_valueType == gmlStringValue) arrow = graphicsObject->m_stringValue; if(id(graphicsObject) == fillPredefKey && graphicsObject->m_valueType == gmlStringValue) fill = graphicsObject->m_stringValue; if (id(graphicsObject) == stipplePredefKey && //line style graphicsObject->m_valueType == gmlIntValue) stipple = graphicsObject->m_intValue; if (id(graphicsObject) == lineWidthPredefKey && //line width graphicsObject->m_valueType == gmlDoubleValue) lineWidth = (float)graphicsObject->m_doubleValue; if (id(graphicsObject) == edgeWeightPredefKey && graphicsObject->m_valueType == gmlDoubleValue) edgeWeight = graphicsObject->m_doubleValue; }//for graphics } case generalizationPredefKey: if (edgeSon->m_valueType != gmlIntValue) break; umlType = (edgeSon->m_intValue == 0) ? Graph::association : Graph::generalization; break; } } // check if everything required is defined correctly if (sourceId == notDefined || targetId == notDefined) { setError("source or target id not defined"); return false; } else if (sourceId < minId || maxId < sourceId || targetId < minId || maxId < targetId) { setError("source or target id out of range"); return false; } // create adjacent nodes if necessary and new edge if (m_mapToNode[sourceId] == nullptr) m_mapToNode[sourceId] = G.newNode(); if (m_mapToNode[targetId] == nullptr) m_mapToNode[targetId] = G.newNode(); edge e = G.newEdge(m_mapToNode[sourceId],m_mapToNode[targetId]); if (AG.attributes() & GraphAttributes::edgeGraphics) AG.bends(e).conc(bends); if (AG.attributes() & GraphAttributes::edgeType) AG.type(e) = umlType; if(AG.attributes() & GraphAttributes::edgeSubGraphs) AG.subGraphBits(e) = subGraph; if (AG.attributes() & GraphAttributes::edgeLabel) AG.label(e) = label; if (AG.attributes() & GraphAttributes::edgeArrow) { if (arrow == "none") AG.arrowType(e) = eaNone; else if (arrow == "last") AG.arrowType(e) = eaLast; else if (arrow == "first") AG.arrowType(e) = eaFirst; else if (arrow == "both") AG.arrowType(e) = eaBoth; else AG.arrowType(e) = eaUndefined; } if (AG.attributes() & GraphAttributes::edgeStyle) { AG.strokeColor(e) = fill; AG.setStrokeType(e, intToStrokeType(stipple)); AG.strokeWidth(e) = lineWidth; } if (AG.attributes() & GraphAttributes::edgeDoubleWeight) AG.doubleWeight(e) = edgeWeight; break; } case directedPredefKey: { if(son->m_valueType != gmlIntValue) break; AG.setDirected(son->m_intValue > 0); break; } } } return true; }//read
//************************************************************* // returns GraphAttributes associated with basic graph i // void SimDraw::getBasicGraphAttributes(int i, GraphAttributes &GA, Graph &G) { G = m_G; GA.init(G,m_GA.attributes()); List<edge> LE; m_G.allEdges(LE); for(edge eLE : LE) if(m_GA.inSubGraph(eLE,i)) { for(node v : G.nodes) { if(compare(GA,v,m_GA,eLE->source())) { if(m_GA.attributes() & GraphAttributes::nodeGraphics) { GA.x(v) = m_GA.x(eLE->source()); GA.y(v) = m_GA.y(eLE->source()); GA.height(v) = m_GA.height(eLE->source()); GA.width(v) = m_GA.width(eLE->source()); } if(m_GA.attributes() & GraphAttributes::nodeId) GA.idNode(v) = m_GA.idNode(eLE->source()); if(m_GA.attributes() & GraphAttributes::nodeLabel) GA.label(v) = m_GA.label(eLE->source()); } if(compare(GA,v,m_GA,eLE->target())) { if(m_GA.attributes() & GraphAttributes::nodeGraphics) { GA.x(v) = m_GA.x(eLE->target()); GA.y(v) = m_GA.y(eLE->target()); GA.height(v) = m_GA.height(eLE->target()); GA.width(v) = m_GA.width(eLE->target()); } if(m_GA.attributes() & GraphAttributes::nodeId) GA.idNode(v) = m_GA.idNode(eLE->target()); if(m_GA.attributes() & GraphAttributes::nodeLabel) GA.label(v) = m_GA.label(eLE->target()); } } for(edge e : G.edges) { if(compare(GA,e->source(),m_GA,eLE->source()) && compare(GA,e->target(),m_GA,eLE->target())) { if(m_GA.attributes() & GraphAttributes::edgeIntWeight) GA.intWeight(e) = m_GA.intWeight(eLE); if(m_GA.attributes() & GraphAttributes::edgeLabel) GA.label(e) = m_GA.label(eLE); if(m_GA.attributes() & GraphAttributes::edgeStyle) GA.strokeColor(e) = m_GA.strokeColor(eLE); if(m_GA.attributes() & GraphAttributes::edgeGraphics) GA.bends(e) = m_GA.bends(eLE); } } } else { List<edge> LE2; G.allEdges(LE2); for(edge e2 : LE2) { if(compare(GA,e2->source(),m_GA,eLE->source()) && compare(GA,e2->target(),m_GA,eLE->target())) { G.delEdge(e2); } } } //remove all Nodes with degree == 0 //this can change the IDs of the nodes in G. List<node> LN; G.allNodes(LN); for(node v : LN) if(v->degree() == 0) G.delNode(v); }//end getBasicGraphAttributes
double LayoutStatistics::angularResolution( const GraphAttributes &ga, double *pMaxAngle, double *pAvgAngle, double *pStdDeviation, bool considerBends) { const Graph &G = ga.constGraph(); double minAngle = 2*Math::pi, maxAngle = 0, sumAngles = 0; int numAngles = 0; ListPure<double> allAngles; for (node v : G.nodes) { double vx = ga.x(v), vy = ga.y(v); List<double> angles; for (adjEntry adj : v->adjEntries) { const DPolyline &dpl = ga.bends(adj->theEdge()); double ex, ey; if (dpl.empty()) { ex = ga.x(adj->twinNode()); ey = ga.y(adj->twinNode()); } else { ex = dpl.front().m_x; ey = dpl.front().m_y; } angles.pushBack(atan2(ex-vx, ey-vy)); } if (angles.size() < 2) continue; numAngles += angles.size(); angles.quicksort(); double lastAngle = angles.back(); for (double psi : angles) { double alpha = psi - lastAngle; if (pStdDeviation) allAngles.pushBack(alpha); sumAngles += alpha; minAngle = min(minAngle, alpha); maxAngle = max(maxAngle, alpha); lastAngle = psi; } } if (considerBends) { for (edge e : G.edges) { DPolyline dpl = ga.bends(e); dpl.pushFront( DPoint(ga.x(e->source()), ga.y(e->source())) ); dpl.pushBack ( DPoint(ga.x(e->target()), ga.y(e->target())) ); dpl.normalize(); if (dpl.size() < 3) continue; for (ListConstIterator<DPoint> it = dpl.begin().succ(); it != dpl.rbegin(); ++it) { double bx = (*it).m_x, by = (*it).m_y; const DPoint &p1 = *it.pred(); double psi1 = atan2(p1.m_x-bx, p1.m_y-by); const DPoint &p2 = *it.succ(); double psi2 = atan2(p2.m_x - bx, p2.m_y - by); double alpha = fabs(psi1 - psi2); if (alpha > Math::pi) alpha -= Math::pi; sumAngles += 2 * Math::pi; minAngle = min(minAngle, alpha); maxAngle = max(maxAngle, alpha + Math::pi); if (pStdDeviation) { numAngles += 2; allAngles.pushBack(alpha); allAngles.pushBack(alpha*Math::pi); } } } } double avgAngle = sumAngles / numAngles; if (pAvgAngle) *pAvgAngle = avgAngle; if (pMaxAngle) *pMaxAngle = maxAngle; if (pStdDeviation) { double sum = 0; for (double alpha : allAngles) { double d = alpha - avgAngle; sum += d*d; } *pStdDeviation = sqrt(sum / numAngles); } return minAngle; }
void VisibilityLayout::layout(GraphAttributes &GA, const UpwardPlanRep &UPROrig) { UpwardPlanRep UPR = UPROrig; //clear some data for(edge e : GA.constGraph().edges) { GA.bends(e).clear(); } int minGridDist = 1; for(node v : GA.constGraph().nodes) { if (minGridDist < max(GA.height(v), GA.width(v))) minGridDist = (int) max(GA.height(v), GA.width(v)); } minGridDist = max(minGridDist*2+1, m_grid_dist); CombinatorialEmbedding &gamma = UPR.getEmbedding(); //add edge (s,t) adjEntry adjSrc = nullptr; for(adjEntry adj : UPR.getSuperSource()->adjEntries) { if (gamma.rightFace(adj) == gamma.externalFace()) adjSrc = adj; break; } OGDF_ASSERT(adjSrc != nullptr); edge e_st = UPR.newEdge(adjSrc, UPR.getSuperSink()); // on the right gamma.computeFaces(); gamma.setExternalFace(gamma.rightFace(e_st->adjSource())); constructVisibilityRepresentation(UPR); // the preliminary postion NodeArray<int> xPos(UPR); NodeArray<int> yPos(UPR); // node Position for(node v : UPR.nodes) { NodeSegment vVis = nodeToVis[v]; int x = (int) (vVis.x_l + vVis.x_r)/2 ; // median positioning xPos[v] = x; yPos[v] = vVis.y; if (UPR.original(v) != nullptr) { node vOrig = UPR.original(v); //final position GA.x(vOrig) = x * minGridDist; GA.y(vOrig) = vVis.y * minGridDist; } } //compute bendpoints for(edge e : GA.constGraph().edges) { const List<edge> &chain = UPR.chain(e); for(edge eUPR : chain) { EdgeSegment eVis = edgeToVis[eUPR]; if (chain.size() == 1) { if ((yPos[eUPR->target()] - yPos[eUPR->source()]) > 1) { DPoint p1(eVis.x*minGridDist, (yPos[eUPR->source()]+1)*minGridDist); DPoint p2(eVis.x*minGridDist, (yPos[eUPR->target()]-1)*minGridDist); GA.bends(e).pushBack(p1); if (yPos[eUPR->source()]+1 != yPos[eUPR->target()]-1) GA.bends(e).pushBack(p2); } } else { //short edge if ((yPos[eUPR->target()] - yPos[eUPR->source()]) == 1) { if (UPR.original(eUPR->target()) == nullptr) { node tgtUPR = eUPR->target(); DPoint p(xPos[tgtUPR]*minGridDist, yPos[tgtUPR]*minGridDist); GA.bends(e).pushBack(p); } } //long edge else { DPoint p1(eVis.x*minGridDist, (yPos[eUPR->source()]+1)*minGridDist); DPoint p2(eVis.x*minGridDist, (yPos[eUPR->target()]-1)*minGridDist); GA.bends(e).pushBack(p1); if (yPos[eUPR->source()]+1 != yPos[eUPR->target()]-1) GA.bends(e).pushBack(p2); if (UPR.original(eUPR->target()) == nullptr) { node tgtUPR = eUPR->target(); DPoint p(xPos[tgtUPR]*minGridDist, yPos[tgtUPR]*minGridDist); GA.bends(e).pushBack(p); } } } } DPolyline &poly = GA.bends(e); DPoint pSrc(GA.x(e->source()), GA.y(e->source())); DPoint pTgt(GA.x(e->target()), GA.y(e->target())); poly.normalize(pSrc, pTgt); } }
void DominanceLayout::layout(GraphAttributes &GA, const UpwardPlanRep &UPROrig) { UpwardPlanRep UPR = UPROrig; //clear some data for(edge e : GA.constGraph().edges) { GA.bends(e).clear(); } //compute and splite transitiv edges List<edge> splitMe; findTransitiveEdges(UPR, splitMe); for(edge eSplit : splitMe) { UPR.getEmbedding().split(eSplit); } // set up first-/lastout, first-/lastin firstout.init(UPR, nullptr); lastout.init(UPR, nullptr); firstin.init(UPR, nullptr); lastin.init(UPR, nullptr); node s = UPR.getSuperSource(); node t = UPR.getSuperSink(); firstout[t] = lastout[t] = nullptr; firstin[s] = lastin[s] = nullptr; firstin[t] = lastin[t] =t->firstAdj()->theEdge(); adjEntry adjRun = s->firstAdj(); while (UPR.getEmbedding().rightFace(adjRun) != UPR.getEmbedding().externalFace()) { adjRun = adjRun->cyclicSucc(); } lastout[s] = adjRun->theEdge(); firstout[s] = adjRun->cyclicSucc()->theEdge(); for(node v : UPR.nodes) { if (v == t || v == s) continue; adjEntry adj = UPR.leftInEdge(v); firstin[v] = adj->theEdge(); firstout[v] = adj->cyclicSucc()->theEdge(); adjEntry adjRightIn = adj; while (adjRightIn->cyclicPred()->theEdge()->source() != v) adjRightIn = adjRightIn->cyclicPred(); lastin[v] = adjRightIn->theEdge(); lastout[v] = adjRightIn->cyclicPred()->theEdge(); } //compute m_L and m_R for min. area drawing m_L = 0; m_R = 0; for(edge e : UPR.edges) { node src = e->source(); node tgt = e->target(); if (lastin[tgt] == e && firstout[src] == e) m_L++; if (firstin[tgt] == e && lastout[src] == e) m_R++; } // compute preleminary coordinate xPreCoord.init(UPR); yPreCoord.init(UPR); int count = 0; labelX(UPR, s, count); count = 0; labelY(UPR, s, count); // compaction compact(UPR, GA); // map coordinate to GA for(node v : GA.constGraph().nodes) { node vUPR = UPR.copy(v); GA.x(v) = xCoord[vUPR]; GA.y(v) = yCoord[vUPR]; } // add bends to original edges for(edge e : GA.constGraph().edges) { const List<edge> &chain = UPR.chain(e); for(edge eChain : chain) { node tgtUPR = eChain->target(); if (tgtUPR != chain.back()->target()) { DPoint p(xCoord[tgtUPR], yCoord[tgtUPR]); GA.bends(e).pushBack(p); } } } //rotate the drawing for(node v : GA.constGraph().nodes) { double r = sqrt(GA.x(v)*GA.x(v) + GA.y(v)*GA.y(v)); if (r == 0) continue; double alpha = asin(GA.y(v)/r); double yNew = sin(alpha + m_angle)*r; double xNew = cos(alpha + m_angle)*r; GA.x(v) = xNew; GA.y(v) = yNew; } for(edge e : GA.constGraph().edges) { DPolyline &poly = GA.bends(e); DPoint pSrc(GA.x(e->source()), GA.y(e->source())); DPoint pTgt(GA.x(e->target()), GA.y(e->target())); poly.normalize(pSrc, pTgt); for(DPoint &p : poly) { double r = p.distance(DPoint(0,0)); if (r == 0) continue; double alpha = asin( p.m_y/r); double yNew = sin(alpha + m_angle)*r; double xNew = cos(alpha + m_angle)*r; p.m_x = xNew; p.m_y = yNew; } } }
void PlanarizationLayoutUML::doSimpleCall(GraphAttributes &GA) { m_nCrossings = 0; if(GA.constGraph().empty()) return; PlanRepUML pr = PlanRepUML(GA); const int numCC = pr.numberOfCCs(); // (width,height) of the layout of each connected component Array<DPoint> boundingBox(numCC); //------------------------------------------ //now planarize CCs and apply drawing module for(int i = 0; i < numCC; ++i) { //--------------------------------------- // 1. crossing minimization //--------------------------------------- int cr; m_crossMin.get().call(pr, i, cr); m_nCrossings += cr; //--------------------------------------- // 2. embed resulting planar graph //--------------------------------------- adjEntry adjExternal = 0; m_embedder.get().call(pr, adjExternal); //--------------------------------------------------------- // 3. compute layout of planarized representation //--------------------------------------------------------- Layout drawing(pr); //call the Layouter for the CC's UMLGraph m_planarLayouter.get().call(pr,adjExternal,drawing); // copy layout into umlGraph // Later, we move nodes and edges in each connected component, such // that no two overlap. for(int j = pr.startNode(); j < pr.stopNode(); ++j) { node vG = pr.v(j); GA.x(vG) = drawing.x(pr.copy(vG)); GA.y(vG) = drawing.y(pr.copy(vG)); adjEntry adj; forall_adj(adj,vG) { if ((adj->index() & 1) == 0) continue; edge eG = adj->theEdge(); drawing.computePolylineClear(pr, eG, GA.bends(eG)); } } // the width/height of the layout has been computed by the planar // layout algorithm; required as input to packing algorithm boundingBox[i] = m_planarLayouter.get().getBoundingBox(); } //---------------------------------------- // 4. arrange layouts of connected components //---------------------------------------- arrangeCCs(pr, GA, boundingBox); }
void ELabelPosSimple::call(GraphAttributes &ug, ELabelInterface<double> &eli) { //ug.addNodeCenter2Bends(); for(edge e : ug.constGraph().edges) { EdgeLabel<double> &el = eli.getLabel(e); DPolyline bends = ug.bends(e); bends.normalize(); if (bends.size() < 2) OGDF_THROW_PARAM(AlgorithmFailureException, afcLabel); double frac; if (m_absolut) { double len = bends.length(); if (len == 0.0) frac = 0.0; else frac = m_marginDistance / len; } else { frac = m_marginDistance; } if (frac < 0.0) frac = 0.0; if (frac > 0.4) frac = 0.4; double midFrac = 0.5; double startFrac = frac; double endFrac = 1.0 -frac; // hole Positionen auf der Kante DPoint midPoint = bends.position(midFrac); DPoint startPoint = bends.position(startFrac); DPoint endPoint = bends.position(endFrac); // hole die beteiligten Segmente DLine midLine = segment(bends, midFrac); DLine startLine = segment(bends, startFrac); DLine endLine = segment(bends, endFrac); // berechne die Labelpositionen if (el.usedLabel(elEnd1)) { DPoint np = leftOfSegment(startLine, startPoint, m_edgeDistance, true); el.setX(elEnd1, np.m_x); el.setY(elEnd1, np.m_y); } if (el.usedLabel(elMult1)) { DPoint np = leftOfSegment(startLine, startPoint, m_edgeDistance, false); el.setX(elMult1, np.m_x); el.setY(elMult1, np.m_y); } if (el.usedLabel(elName)) { DPoint np = m_midOnEdge ? midPoint : leftOfSegment(midLine, midPoint, m_edgeDistance, true); el.setX(elName, np.m_x); el.setY(elName, np.m_y); } if (el.usedLabel(elEnd2)) { DPoint np = leftOfSegment(endLine, endPoint, m_edgeDistance, true); el.setX(elEnd2, np.m_x); el.setY(elEnd2, np.m_y); } if (el.usedLabel(elMult2)) { DPoint np = leftOfSegment(endLine, endPoint, m_edgeDistance, false); el.setX(elMult2, np.m_x); el.setY(elMult2, np.m_y); } } }
bool GmlParser::read(Graph &G, GraphAttributes &AG) { OGDF_ASSERT(&G == &(AG.constGraph())) G.clear(); int minId = m_mapToNode.low(); int maxId = m_mapToNode.high(); int notDefined = minId-1; //indicates not defined id key DPolyline bends; GmlObject *son = m_graphObject->m_pFirstSon; for(; son; son = son->m_pBrother) { switch(id(son)) { case nodePredefKey: { if (son->m_valueType != gmlListBegin) break; // set attributes to default values int vId = notDefined; double x = 0, y = 0, w = 0, h = 0; String label; String templ; String fill; // the fill color attribute String line; // the line color attribute String shape; //the shape type double lineWidth = 1.0; //node line width int pattern = 1; //node brush pattern int stipple = 1; //line style pattern // read all relevant attributes GmlObject *nodeSon = son->m_pFirstSon; for(; nodeSon; nodeSon = nodeSon->m_pBrother) { switch(id(nodeSon)) { case idPredefKey: if(nodeSon->m_valueType != gmlIntValue) break; vId = nodeSon->m_intValue; break; case graphicsPredefKey: { if (nodeSon->m_valueType != gmlListBegin) break; GmlObject *graphicsObject = nodeSon->m_pFirstSon; for(; graphicsObject; graphicsObject = graphicsObject->m_pBrother) { switch(id(graphicsObject)) { case xPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; x = graphicsObject->m_doubleValue; break; case yPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; y = graphicsObject->m_doubleValue; break; case wPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; w = graphicsObject->m_doubleValue; break; case hPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; h = graphicsObject->m_doubleValue; break; case fillPredefKey: if(graphicsObject->m_valueType != gmlStringValue) break; fill = graphicsObject->m_stringValue; break; case linePredefKey: if(graphicsObject->m_valueType != gmlStringValue) break; line = graphicsObject->m_stringValue; break; case lineWidthPredefKey: if(graphicsObject->m_valueType != gmlDoubleValue) break; lineWidth = graphicsObject->m_doubleValue; break; case typePredefKey: if(graphicsObject->m_valueType != gmlStringValue) break; shape = graphicsObject->m_stringValue; break; case patternPredefKey: //fill style if(graphicsObject->m_valueType != gmlIntValue) break; pattern = graphicsObject->m_intValue; case stipplePredefKey: //line style if(graphicsObject->m_valueType != gmlIntValue) break; stipple = graphicsObject->m_intValue; } } break; } case templatePredefKey: if (nodeSon->m_valueType != gmlStringValue) break; templ = nodeSon->m_stringValue; break; case labelPredefKey: if (nodeSon->m_valueType != gmlStringValue) break; label = nodeSon->m_stringValue; break; } } // check if everything required is defined correctly if (vId == notDefined) { setError("node id not defined"); return false; } // create new node if necessary and assign attributes if (m_mapToNode[vId] == 0) m_mapToNode[vId] = G.newNode(); if (AG.attributes() & GraphAttributes::nodeGraphics) { AG.x(m_mapToNode[vId]) = x; AG.y(m_mapToNode[vId]) = y; AG.width (m_mapToNode[vId]) = w; AG.height(m_mapToNode[vId]) = h; if (shape == "oval") AG.shapeNode(m_mapToNode[vId]) = GraphAttributes::oval; else AG.shapeNode(m_mapToNode[vId]) = GraphAttributes::rectangle; } if ( (AG.attributes() & GraphAttributes::nodeColor) && (AG.attributes() & GraphAttributes::nodeGraphics) ) { AG.colorNode(m_mapToNode[vId]) = fill; AG.nodeLine(m_mapToNode[vId]) = line; } if (AG.attributes() & GraphAttributes::nodeLabel) AG.labelNode(m_mapToNode[vId]) = label; if (AG.attributes() & GraphAttributes::nodeTemplate) AG.templateNode(m_mapToNode[vId]) = templ; if (AG.attributes() & GraphAttributes::nodeId) AG.idNode(m_mapToNode[vId]) = vId; if (AG.attributes() & GraphAttributes::nodeStyle) { AG.nodePattern(m_mapToNode[vId]) = GraphAttributes::intToPattern(pattern); AG.styleNode(m_mapToNode[vId]) = GraphAttributes::intToStyle(stipple); AG.lineWidthNode(m_mapToNode[vId]) = lineWidth; } }//node //Todo: line style set stipple value break; case edgePredefKey: { String arrow; // the arrow type attribute String fill; //the color fill attribute int stipple = 1; //the line style double lineWidth = 1.0; double edgeWeight = 1.0; int subGraph = 0; //edgeSubGraph attribute String label; // label attribute if (son->m_valueType != gmlListBegin) break; // set attributes to default values int sourceId = notDefined, targetId = notDefined; Graph::EdgeType umlType = Graph::association; // read all relevant attributes GmlObject *edgeSon = son->m_pFirstSon; for(; edgeSon; edgeSon = edgeSon->m_pBrother) { switch(id(edgeSon)) { case sourcePredefKey: if (edgeSon->m_valueType != gmlIntValue) break; sourceId = edgeSon->m_intValue; break; case targetPredefKey: if (edgeSon->m_valueType != gmlIntValue) break; targetId = edgeSon->m_intValue; break; case subGraphPredefKey: if (edgeSon->m_valueType != gmlIntValue) break; subGraph = edgeSon->m_intValue; break; case labelPredefKey: if (edgeSon->m_valueType != gmlStringValue) break; label = edgeSon->m_stringValue; break; case graphicsPredefKey: { if (edgeSon->m_valueType != gmlListBegin) break; GmlObject *graphicsObject = edgeSon->m_pFirstSon; for(; graphicsObject; graphicsObject = graphicsObject->m_pBrother) { if(id(graphicsObject) == LinePredefKey && graphicsObject->m_valueType == gmlListBegin) { readLineAttribute(graphicsObject->m_pFirstSon,bends); } if(id(graphicsObject) == arrowPredefKey && graphicsObject->m_valueType == gmlStringValue) arrow = graphicsObject->m_stringValue; if(id(graphicsObject) == fillPredefKey && graphicsObject->m_valueType == gmlStringValue) fill = graphicsObject->m_stringValue; if (id(graphicsObject) == stipplePredefKey && //line style graphicsObject->m_valueType == gmlIntValue) stipple = graphicsObject->m_intValue; if (id(graphicsObject) == lineWidthPredefKey && //line width graphicsObject->m_valueType == gmlDoubleValue) lineWidth = graphicsObject->m_doubleValue; if (id(graphicsObject) == edgeWeightPredefKey && graphicsObject->m_valueType == gmlDoubleValue) edgeWeight = graphicsObject->m_doubleValue; }//for graphics } case generalizationPredefKey: if (edgeSon->m_valueType != gmlIntValue) break; umlType = (edgeSon->m_intValue == 0) ? Graph::association : Graph::generalization; break; } } // check if everything required is defined correctly if (sourceId == notDefined || targetId == notDefined) { setError("source or target id not defined"); return false; } else if (sourceId < minId || maxId < sourceId || targetId < minId || maxId < targetId) { setError("source or target id out of range"); return false; } // create adjacent nodes if necessary and new edge if (m_mapToNode[sourceId] == 0) m_mapToNode[sourceId] = G.newNode(); if (m_mapToNode[targetId] == 0) m_mapToNode[targetId] = G.newNode(); edge e = G.newEdge(m_mapToNode[sourceId],m_mapToNode[targetId]); if (AG.attributes() & GraphAttributes::edgeGraphics) AG.bends(e).conc(bends); if (AG.attributes() & GraphAttributes::edgeType) AG.type(e) = umlType; if(AG.attributes() & GraphAttributes::edgeSubGraph) AG.subGraphBits(e) = subGraph; if (AG.attributes() & GraphAttributes::edgeLabel) AG.labelEdge(e) = label; if (AG.attributes() & GraphAttributes::edgeArrow) if (arrow == "none") AG.arrowEdge(e) = GraphAttributes::none; else if (arrow == "last") AG.arrowEdge(e) = GraphAttributes::last; else if (arrow == "first") AG.arrowEdge(e) = GraphAttributes::first; else if (arrow == "both") AG.arrowEdge(e) = GraphAttributes::both; else AG.arrowEdge(e) = GraphAttributes::undefined; if (AG.attributes() & GraphAttributes::edgeColor) AG.colorEdge(e) = fill; if (AG.attributes() & GraphAttributes::edgeStyle) { AG.styleEdge(e) = AG.intToStyle(stipple); AG.edgeWidth(e) = lineWidth; } if (AG.attributes() & GraphAttributes::edgeDoubleWeight) AG.doubleWeight(e) = edgeWeight; break; } case directedPredefKey: { if(son->m_valueType != gmlIntValue) break; AG.directed(son->m_intValue > 0); break; } } } return true; }//read