void MultilevelGraph::prepareGraphAttributes(GraphAttributes &GA) const { long additionalAttributes = 0; if (!(GA.attributes() & GraphAttributes::edgeDoubleWeight)) { additionalAttributes |= GraphAttributes::edgeDoubleWeight; } if (!(GA.attributes() & GraphAttributes::nodeWeight)) { additionalAttributes |= GraphAttributes::nodeWeight; } GA.initAttributes(additionalAttributes); }
void ComponentSplitterLayout::call(GraphAttributes &GA) { // Only do preparations and call if layout is valid if (m_secondaryLayout.valid()) { //first we split the graph into its components const Graph& G = GA.constGraph(); NodeArray<int> componentNumber(G); m_numberOfComponents = connectedComponents(G, componentNumber); if (m_numberOfComponents == 0) { return; } //std::vector< std::vector<node> > componentArray; //componentArray.resize(numComponents); //Array<GraphAttributes *> components(numComponents); // // intialize the array of lists of nodes contained in a CC nodesInCC.init(m_numberOfComponents); node v; forall_nodes(v,G) nodesInCC[componentNumber[v]].pushBack(v); // Create copies of the connected components and corresponding // GraphAttributes GraphCopy GC; GC.createEmpty(G); EdgeArray<edge> auxCopy(G); for (int i = 0; i < m_numberOfComponents; i++) { GC.initByNodes(nodesInCC[i],auxCopy); GraphAttributes cGA(GC, GA.attributes()); //copy information into copy GA forall_nodes(v, GC) { cGA.width(v) = GA.width(GC.original(v)); cGA.height(v) = GA.height(GC.original(v)); cGA.x(v) = GA.x(GC.original(v)); cGA.y(v) = GA.y(GC.original(v)); } // copy information on edges if (GA.attributes() & GraphAttributes::edgeDoubleWeight) { edge e; forall_edges(e, GC) { cGA.doubleWeight(e) = GA.doubleWeight(GC.original(e)); } }
static inline bool readVizAttribute( GraphAttributes &GA, node v, const pugi::xml_node tag) { const long attrs = GA.attributes(); if(string(tag.name()) == "viz:position") { if(attrs & GraphAttributes::nodeGraphics) { pugi::xml_attribute xAttr = tag.attribute("x"); pugi::xml_attribute yAttr = tag.attribute("y"); pugi::xml_attribute zAttr = tag.attribute("z"); if(!xAttr || !yAttr) { GraphIO::logger.lout() << "Missing \"x\" or \"y\" in position tag." << std::endl; return false; } GA.x(v) = xAttr.as_int(); GA.y(v) = yAttr.as_int(); // z attribute is optional and avaliable only in \a threeD mode GA.y(v) = yAttr.as_int(); if (zAttr && (attrs & GraphAttributes::threeD)) { GA.z(v) = zAttr.as_int(); } } } else if(string(tag.name()) == "viz:size") { if(attrs & GraphAttributes::nodeGraphics) { pugi::xml_attribute valueAttr = tag.attribute("value"); if (!valueAttr) { GraphIO::logger.lout() << "\"size\" attribute is missing a value." << std::endl; return false; } double size = valueAttr.as_double(); GA.width(v) = size * LayoutStandards::defaultNodeWidth(); GA.height(v) = size * LayoutStandards::defaultNodeHeight(); } } else if(string(tag.name()) == "viz:shape") { if(attrs & GraphAttributes::nodeGraphics) { pugi::xml_attribute valueAttr = tag.attribute("value"); if(!valueAttr) { GraphIO::logger.lout() << "\"shape\" attribute is missing a value." << std::endl; return false; } GA.shape(v) = toShape(valueAttr.value()); } } else if(string(tag.name()) == "viz:color") { if(attrs & GraphAttributes::nodeStyle) { return readColor(GA.fillColor(v), tag); } } else { GraphIO::logger.lout() << "Incorrect tag: \"" << tag.name() << "\"." << std::endl; return false; } return true; }
static inline bool readVizAttribute( GraphAttributes &GA, edge e, const pugi::xml_node tag) { const long attrs = GA.attributes(); if(string(tag.name()) == "viz:color") { if(attrs & GraphAttributes::edgeStyle) { return readColor(GA.strokeColor(e), tag); } } else if(string(tag.name()) == "viz:thickness") { auto thickAttr = tag.attribute("value"); if(!thickAttr) { GraphIO::logger.lout() << "Missing \"value\" on thickness tag." << std::endl; return false; } if(attrs & GraphAttributes::edgeDoubleWeight) { GA.doubleWeight(e) = thickAttr.as_double(); } else if(attrs & GraphAttributes::edgeIntWeight) { GA.intWeight(e) = thickAttr.as_int(); } } else if(string(tag.name()) == "viz:shape") { // Values: solid, dotted, dashed, double. Not supported in OGDF. } else { GraphIO::logger.lout() << "Incorrect tag \"" << tag.name() << "\"." << std::endl; return false; } return true; }
bool GraphMLParser::readData( GraphAttributes &GA, const node &v, const XmlTagObject &nodeData) { XmlAttributeObject *keyId; nodeData.findXmlAttributeObjectByName("key", keyId); if(keyId == NULL) { cerr << "ERROR: Node data does not have a key.\n"; return false; } const long attrs = GA.attributes(); std::stringstream value(nodeData.getValue()); switch (graphml::toAttribute(m_attrName[keyId->getValue()])) { case graphml::a_nodeLabel: if(attrs & GraphAttributes::nodeLabel) { value >> GA.label(v); } break; case graphml::a_x: if(attrs & GraphAttributes::nodeGraphics) { value >> GA.x(v); }
static bool inline readAttribute( GraphAttributes &GA, node v, const NodeAttribute &attr, const std::string &value) { const long attrs = GA.attributes(); switch(attr) { case na_name: // Not really an attribute, handled elsewhere. break; case na_label: if(attrs & GraphAttributes::nodeLabel) { GA.label(v) = value; } break; case na_x: if(attrs & GraphAttributes::nodeGraphics) { std::istringstream is(value); is >> GA.x(v); } break; case na_y: if(attrs & GraphAttributes::nodeGraphics) { std::istringstream is(value); is >> GA.y(v); }
void StressMinimization::call(GraphAttributes& GA) { const Graph& G = GA.constGraph(); // if the graph has at most one node nothing to do if (G.numberOfNodes() <= 1) { // make it exception save for(node v : G.nodes) { GA.x(v) = 0; GA.y(v) = 0; } return; } if (m_componentLayout && !isConnected(G)) { OGDF_THROW(PreconditionViolatedException); return; } NodeArray<NodeArray<double> > shortestPathMatrix(G); NodeArray<NodeArray<double> > weightMatrix(G); initMatrices(G, shortestPathMatrix, weightMatrix); // if the edge costs are defined by the attribute copy it to an array and // construct the proper shortest path matrix if (m_hasEdgeCostsAttribute) { if (!(GA.attributes() & GraphAttributes::edgeDoubleWeight)) { OGDF_THROW(PreconditionViolatedException); return; } m_avgEdgeCosts = dijkstra_SPAP(GA, shortestPathMatrix); // compute shortest path all pairs } else { m_avgEdgeCosts = m_edgeCosts; bfs_SPAP(G, shortestPathMatrix, m_edgeCosts); } call(GA, shortestPathMatrix, weightMatrix); }
static inline void writeAttributes( std::ostream &out, int depth, const GraphAttributes &GA, edge e) { const long attrs = GA.attributes(); if(attrs & GraphAttributes::edgeStyle) { const Color &color = GA.strokeColor(e); const int red = color.red(); const int green = color.green(); const int blue = color.blue(); const int alpha = color.alpha(); GraphIO::indent(out, depth) << "<viz:color " << "red=\"" << red << "\" " << "green=\"" << green << "\" " << "blue=\"" << blue << "\" " << "alpha=\"" << alpha << "\" " << "/>\n"; } if(attrs & GraphAttributes::edgeDoubleWeight) { const double weight = GA.doubleWeight(e); GraphIO::indent(out, depth) << "<viz:thickness " << "value=\"" << weight << "\" " << "/>\n"; } else if(attrs & GraphAttributes::edgeIntWeight) { const int weight = GA.intWeight(e); GraphIO::indent(out, depth) << "<viz:thickness " << "value=\"" << weight << "\" " << "/>\n"; } /* * Edge type and arrow are not supported by VIZ module. Therefore, they * need to be written using <attvalues> tag (for estetic reasons, we write * them only if either of them is present). For convenience reasons, we use * the same names and values as in GraphML format. */ if(!(attrs & (GraphAttributes::edgeType | GraphAttributes::edgeArrow))) { return; } GraphIO::indent(out, depth) << "<attvalues>\n"; if(attrs & GraphAttributes::edgeType) { writeAttValue( out, depth + 1, graphml::a_edgeType, graphml::toString(GA.type(e))); } if(attrs & GraphAttributes::edgeArrow) { writeAttValue( out, depth + 1, graphml::a_edgeArrow, graphml::toString(GA.arrowType(e))); } GraphIO::indent(out, depth) << "</attvalues>\n"; }
void BertaultLayout::call(GraphAttributes &AG) { const Graph &G = AG.constGraph(); if(G.numberOfNodes() == 0) return; if( (AG.attributes() & GraphAttributes::nodeGraphics) == 0 ) return; if( (AG.attributes() & GraphAttributes::edgeGraphics) != 0 ) AG.clearAllBends(); if(iter_no==0) iter_no=G.numberOfNodes()*10; if(req_length==0) { edge e; forall_edges(e,G) { node a=e->source(); node b=e->target(); req_length+=sqrt((AG.x(a)-AG.x(b))*(AG.x(a)-AG.x(b))+(AG.y(a)-AG.y(b))*(AG.y(a)-AG.y(b))); }
void StressMinimization::minimizeStress( GraphAttributes& GA, NodeArray<NodeArray<double> >& shortestPathMatrix, NodeArray<NodeArray<double> >& weightMatrix) { const Graph& G = GA.constGraph(); int numberOfPerformedIterations = 0; double prevStress = numeric_limits<double>::max(); double curStress = numeric_limits<double>::max(); if (m_terminationCriterion == STRESS) { curStress = calcStress(GA, shortestPathMatrix, weightMatrix); } NodeArray<double> newX; NodeArray<double> newY; NodeArray<double> newZ; if (m_terminationCriterion == POSITION_DIFFERENCE) { newX.init(G); newY.init(G); if (GA.attributes() & GraphAttributes::threeD) newZ.init(G); } do { if (m_terminationCriterion == POSITION_DIFFERENCE) { if (GA.attributes() & GraphAttributes::threeD) copyLayout(GA, newX, newY, newZ); else copyLayout(GA, newX, newY); } nextIteration(GA, shortestPathMatrix, weightMatrix); if (m_terminationCriterion == STRESS) { prevStress = curStress; curStress = calcStress(GA, shortestPathMatrix, weightMatrix); } } while (!finished(GA, ++numberOfPerformedIterations, newX, newY, prevStress, curStress)); Logger::slout() << "Iteration count:\t" << numberOfPerformedIterations << "\tStress:\t" << calcStress(GA, shortestPathMatrix, weightMatrix) << endl; }
static inline void writeAttributes( std::ostream &out, const GraphAttributes &GA, const node &v) { const long flags = GA.attributes(); out << "["; bool separator = false; // Wheter to put separator before attribute. if(flags & GraphAttributes::nodeId) { writeAttribute(out, separator, "id", GA.idNode(v)); } if(flags & GraphAttributes::nodeLabel) { writeAttribute(out, separator, "label", GA.label(v)); } if(flags & GraphAttributes::nodeTemplate) { writeAttribute(out, separator, "comment", GA.templateNode(v)); } if(flags & GraphAttributes::nodeGraphics) { writeAttribute(out, separator, "width", GA.width(v)); writeAttribute(out, separator, "height", GA.height(v)); writeAttribute(out, separator, "shape", dot::toString(GA.shape(v))); out << ", pos=\"" << GA.x(v) << "," << GA.y(v); if(flags & GraphAttributes::threeD) { out << "," << GA.z(v); } out << "\""; } if(flags & GraphAttributes::nodeStyle) { writeAttribute(out, separator, "color", GA.strokeColor(v)); writeAttribute(out, separator, "fillcolor", GA.fillColor(v)); writeAttribute(out, separator, "stroketype", toString(GA.strokeType(v))); writeAttribute(out, separator, "strokewidth", GA.strokeWidth(v)); writeAttribute(out, separator, "fillpattern", toString(GA.fillPattern(v))); } if(flags & GraphAttributes::nodeType) { writeAttribute(out, separator, "type", int(GA.type(v))); } if(flags & GraphAttributes::nodeWeight) { writeAttribute(out, separator, "weight", GA.weight(v)); } out << "]"; }
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 << "]"; }
bool GraphMLParser::readData( GraphAttributes &GA, const edge &e, const pugi::xml_node edgeData) { pugi::xml_attribute keyId = edgeData.attribute("key"); if (!keyId) { GraphIO::logger.lout() << "Edge data does not have a key." << endl; return false; } const long attrs = GA.attributes(); pugi::xml_text text = edgeData.text(); switch(graphml::toAttribute(m_attrName[keyId.value()])) { case graphml::a_edgeLabel: if(attrs & GraphAttributes::edgeLabel) { GA.label(e) = text.get(); } break; case graphml::a_edgeWeight: if(attrs & GraphAttributes::edgeIntWeight) { GA.intWeight(e) = text.as_int(); } else if(attrs & GraphAttributes::edgeDoubleWeight) { GA.doubleWeight(e) = text.as_double(); } break; case graphml::a_edgeType: if(attrs & GraphAttributes::edgeType) { GA.type(e) = graphml::toEdgeType(text.get()); } break; case graphml::a_edgeArrow: if(attrs & GraphAttributes::edgeArrow) { GA.arrowType(e) = graphml::toArrow(text.get()); } break; case graphml::a_edgeStroke: if(attrs & GraphAttributes::edgeStyle) { GA.strokeColor(e) = text.get(); } break; default: GraphIO::logger.lout(Logger::LL_MINOR) << "Unknown edge attribute with \"" << keyId.value() << "\"." << endl; } return true; }
static inline void writeAttributes( std::ostream &out, const GraphAttributes &GA, const node &v) { const long flags = GA.attributes(); out << "["; bool separator = false; // Wheter to put separator before attribute. if(flags & GraphAttributes::nodeId) { writeAttribute(out, separator, "id", GA.idNode(v)); } if(flags & GraphAttributes::nodeLabel) { writeAttribute(out, separator, "label", GA.label(v)); } if(flags & GraphAttributes::nodeTemplate) { writeAttribute(out, separator, "comment", GA.templateNode(v)); } if(flags & GraphAttributes::nodeGraphics) { writeAttribute(out, separator, "width", GA.width(v)); writeAttribute(out, separator, "height", GA.height(v)); writeAttribute(out, separator, "shape", dot::toString(GA.shape(v))); out << ", pos=\"" << GA.x(v) << "," << GA.y(v); if(flags & GraphAttributes::threeD) { out << "," << GA.z(v); } out << "\""; } if(flags & GraphAttributes::nodeStyle) { writeAttribute(out, separator, "color", GA.strokeColor(v)); writeAttribute(out, separator, "fillcolor", GA.fillColor(v)); } // NOTE: Node type is weird and (probably) cannot be mapped to DOT. // NOTE: Node weight is not supported. out << "]"; }
static void compute_bounding_box(const GraphAttributes &A, double &xmin, double &ymin, double &xmax, double &ymax) { const Graph &G = A.constGraph(); if(G.numberOfNodes() == 0) { xmin = xmax = ymin = ymax = 0; return; } node v = G.firstNode(); xmin = xmax = A.x(v), ymin = ymax = A.y(v); forall_nodes(v, G) { double lw = (A.attributes() & GraphAttributes::nodeStyle) ? 0.5*A.strokeWidth(v) : 0.5; xmax = max(xmax, A.x(v) + A.width (v)/2 + lw); ymax = max(ymax, A.y(v) + A.height(v)/2 + lw); xmin = min(xmin, A.x(v) - A.width (v)/2 - lw); ymin = min(ymin, A.y(v) - A.height(v)/2 - lw); }
static inline void readAttValue( GraphAttributes &GA, node v, const std::string &name, const std::string &value) { const long attrs = GA.attributes(); // For not "viz" attributes, we use GraphML ones. switch(graphml::toAttribute(name)) { case graphml::Attribute::NodeType: if(attrs & GraphAttributes::nodeType) { GA.type(v) = graphml::toNodeType(value); } break; case graphml::Attribute::Template: if(attrs & GraphAttributes::nodeTemplate) { GA.templateNode(v) = value; } break; case graphml::Attribute::NodeWeight: if(attrs & GraphAttributes::nodeWeight) { std::istringstream ss(value); ss >> GA.weight(v); } break; case graphml::Attribute::NodeStrokeType: if(attrs & GraphAttributes::nodeStyle) { GA.strokeType(v) = fromString<StrokeType>(value); } break; case graphml::Attribute::NodeFillPattern: if(attrs & GraphAttributes::nodeStyle) { GA.fillPattern(v) = fromString<FillPattern>(value); } break; case graphml::Attribute::NodeStrokeWidth: if(attrs & GraphAttributes::nodeWeight) { std::istringstream ss(value); ss >> GA.strokeWidth(v); }
static inline void defineAttributes( std::ostream &out, int depth, const GraphAttributes &GA) { const long attrs = GA.attributes(); // Declare node attributes. GraphIO::indent(out, depth) << "<attributes class=\"node\">\n"; if(attrs & GraphAttributes::nodeType) { defineAttribute( out, depth + 1, graphml::toString(graphml::a_nodeType), "string"); } if(attrs & GraphAttributes::nodeTemplate) { defineAttribute( out, depth + 1, graphml::toString(graphml::a_template), "string"); } if(attrs & GraphAttributes::nodeWeight) { defineAttribute( out, depth + 1, graphml::toString(graphml::a_nodeWeight), "float"); } GraphIO::indent(out, depth) << "</attributes>\n"; // Declare edge attributes. GraphIO::indent(out, depth) << "<attributes class=\"edge\">\n"; if(attrs & GraphAttributes::edgeType) { defineAttribute( out, depth + 1, graphml::toString(graphml::a_edgeType), "string"); } if(attrs & GraphAttributes::edgeArrow) { defineAttribute( out, depth + 1, graphml::toString(graphml::a_edgeArrow), "string"); } GraphIO::indent(out, depth) << "</attributes>\n"; }
static inline bool readVizAttribute( GraphAttributes &GA, node v, const XmlTagObject &tag) { const long attrs = GA.attributes(); if(tag.getName() == "viz:position") { if(attrs & GraphAttributes::nodeGraphics) { XmlAttributeObject *xAttr, *yAttr, *zAttr; tag.findXmlAttributeObjectByName("x", xAttr); tag.findXmlAttributeObjectByName("y", yAttr); tag.findXmlAttributeObjectByName("z", zAttr); if(!xAttr || !yAttr) { OGDF_ERROR("Missing \"x\" or \"y\" on position tag " << "(line " << tag.getLine() << ")."); return false; } std::istringstream is; is.clear(); is.str(xAttr->getValue()); is >> GA.x(v); is.clear(); is.str(yAttr->getValue()); is >> GA.y(v); // z attribute is optional and avaliable only in \a threeD mode. if(zAttr && (attrs & GraphAttributes::threeD)) { is.clear(); is.str(zAttr->getValue()); is >> GA.z(v); } }
double StressMinimization::calcStress( const GraphAttributes& GA, NodeArray<NodeArray<double> >& shortestPathMatrix, NodeArray<NodeArray<double> >& weightMatrix) { double stress = 0; for (node v = GA.constGraph().firstNode(); v != nullptr; v = v->succ()) { for (node w = v->succ(); w != nullptr; w = w->succ()) { double xDiff = GA.x(v) - GA.x(w); double yDiff = GA.y(v) - GA.y(w); double zDiff = 0.0; if (GA.attributes() & GraphAttributes::threeD) { zDiff = GA.z(v) - GA.z(w); } double dist = sqrt(xDiff * xDiff + yDiff * yDiff + zDiff * zDiff); if (dist != 0) { stress += weightMatrix[v][w] * (shortestPathMatrix[v][w] - dist) * (shortestPathMatrix[v][w] - dist);// } } } return stress; }
static inline void writeAttributes( std::ostream &out, int depth, const GraphAttributes &GA, node v) { const long attrs = GA.attributes(); if(attrs & GraphAttributes::nodeGraphics) { const double z = (attrs & GraphAttributes::threeD) ? GA.z(v) : 0.0; GraphIO::indent(out, depth) << "<viz:position " << "x=\"" << GA.x(v) << "\" " << "y=\"" << GA.y(v) << "\" " << "z=\"" << z << "\" " << "/>\n"; // TODO: size is a scale here, so we have to know average size first. // const double size = std::max(GA.width(v), GA.height(v)); // GraphIO::indent(out, depth) << "<viz:size " // << "value=\"" << size << "\" " // << "/>\n"; const Shape shape = GA.shape(v); GraphIO::indent(out, depth) << "<viz:shape " << "value=\"" << toString(shape) << "\" " << "/>\n"; } if(attrs & GraphAttributes::nodeStyle) { const Color &color = GA.fillColor(v); const int red = color.red(); const int green = color.green(); const int blue = color.blue(); const int alpha = color.alpha(); GraphIO::indent(out, depth) << "<viz:color " << "red=\"" << red << "\" " << "green=\"" << green << "\" " << "blue=\"" << blue << "\" " << "alpha=\"" << alpha << "\" " << "/>\n"; } /* * Node type, template and weight are not supported by VIZ module. So, they * need to be written using <attvalues> tag (for estetic reasons, we write * them only if either of them is present). For convenience reasons, we use * the same names and values as in GraphML format. */ if(!(attrs & (GraphAttributes::nodeType | GraphAttributes::nodeTemplate | GraphAttributes::nodeWeight))) { return; } GraphIO::indent(out, depth) << "<attvalues>\n"; if(attrs & GraphAttributes::nodeType) { writeAttValue( out, depth + 1, graphml::a_nodeType, graphml::toString(GA.type(v))); } if(attrs & GraphAttributes::nodeTemplate) { writeAttValue(out, depth + 1, graphml::a_template, GA.templateNode(v)); } if(attrs & GraphAttributes::nodeWeight) { writeAttValue(out, depth + 1, graphml::a_nodeWeight, GA.weight(v)); } GraphIO::indent(out, depth) << "</attvalues>\n"; }
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
void ComponentSplitterLayout::call(GraphAttributes &GA) { // Only do preparations and call if layout is valid if (m_secondaryLayout.valid()) { //first we split the graph into its components const Graph& G = GA.constGraph(); NodeArray<int> componentNumber(G); int numberOfComponents = connectedComponents(G, componentNumber); if (numberOfComponents == 0) { return; } // intialize the array of lists of nodes contained in a CC Array<List<node> > nodesInCC(numberOfComponents); for(node v : G.nodes) nodesInCC[componentNumber[v]].pushBack(v); // Create copies of the connected components and corresponding // GraphAttributes GraphCopy GC; GC.createEmpty(G); EdgeArray<edge> auxCopy(G); for (int i = 0; i < numberOfComponents; i++) { GC.initByNodes(nodesInCC[i],auxCopy); GraphAttributes cGA(GC, GA.attributes()); //copy information into copy GA for(node v : GC.nodes) { cGA.width(v) = GA.width(GC.original(v)); cGA.height(v) = GA.height(GC.original(v)); cGA.x(v) = GA.x(GC.original(v)); cGA.y(v) = GA.y(GC.original(v)); } // copy information on edges if (GA.attributes() & GraphAttributes::edgeDoubleWeight) { for (edge e : GC.edges) { cGA.doubleWeight(e) = GA.doubleWeight(GC.original(e)); } } m_secondaryLayout.get().call(cGA); //copy layout information back into GA for(node v : GC.nodes) { node w = GC.original(v); if (w != nullptr) { GA.x(w) = cGA.x(v); GA.y(w) = cGA.y(v); if (GA.attributes() & GraphAttributes::threeD) { GA.z(w) = cGA.z(v); } } } } // rotate component drawings and call the packer reassembleDrawings(GA, nodesInCC); }//if valid }
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
bool GraphMLParser::readData( GraphAttributes &GA, const node &v, const pugi::xml_node nodeData) { pugi::xml_attribute keyId = nodeData.attribute("key"); if (!keyId) { GraphIO::logger.lout() << "Node data does not have a key." << endl; return false; } const long attrs = GA.attributes(); pugi::xml_text text = nodeData.text(); switch (graphml::toAttribute(m_attrName[keyId.value()])) { case graphml::a_nodeLabel: if(attrs & GraphAttributes::nodeLabel) { GA.label(v) = text.get(); } break; case graphml::a_x: if(attrs & GraphAttributes::nodeGraphics) { GA.x(v) = text.as_double(); } break; case graphml::a_y: if(attrs & GraphAttributes::nodeGraphics) { GA.y(v) = text.as_double();; } break; case graphml::a_width: if(attrs & GraphAttributes::nodeGraphics) { GA.width(v) = text.as_double(); } break; case graphml::a_height: if(attrs & GraphAttributes::nodeGraphics) { GA.height(v) = text.as_double(); } break; case graphml::a_size: if(attrs & GraphAttributes::nodeGraphics) { double size = text.as_double(); // We want to set a new size only if width and height was not set. if (GA.height(v) == GA.width(v)) { GA.height(v) = GA.width(v) = size; } } break; case graphml::a_shape: if(attrs & GraphAttributes::nodeGraphics) { GA.shape(v) = graphml::toShape(text.get()); } break; case graphml::a_z: if(attrs & GraphAttributes::threeD) { GA.z(v) = text.as_double(); } break; case graphml::a_r: if (attrs & GraphAttributes::nodeStyle && !GraphIO::setColorValue(text.as_int(), [&](uint8_t val) { GA.fillColor(v).red(val); })) { return false; } break; case graphml::a_g: if(attrs & GraphAttributes::nodeStyle && !GraphIO::setColorValue(text.as_int(), [&](uint8_t val) { GA.fillColor(v).green(val); })) { return false; } break; case graphml::a_b: if(attrs & GraphAttributes::nodeStyle && !GraphIO::setColorValue(text.as_int(), [&](uint8_t val) { GA.fillColor(v).blue(val); })) { return false; } break; case graphml::a_nodeFill: if(attrs & GraphAttributes::nodeStyle) { GA.fillColor(v) = text.get(); } break; case graphml::a_nodeStroke: if(attrs & GraphAttributes::nodeStyle) { GA.strokeColor(v) = text.get(); } break; case graphml::a_nodeType: if(attrs & GraphAttributes::nodeType) { GA.type(v) = graphml::toNodeType(text.get()); } break; case graphml::a_template: if(attrs & GraphAttributes::nodeTemplate) { GA.templateNode(v) = text.get(); } break; case graphml::a_nodeWeight: if(attrs & GraphAttributes::nodeWeight) { GA.weight(v) = text.as_int(); } break; default: GraphIO::logger.lout(Logger::LL_MINOR) << "Unknown node attribute: \"" << keyId.value() << "\"." << endl; } return true; }
void StressMinimization::nextIteration( GraphAttributes& GA, NodeArray<NodeArray<double> >& shortestPathMatrix, NodeArray<NodeArray<double> >& weights) { const Graph& G = GA.constGraph(); for (node v : G.nodes) { double newXCoord = 0.0; double newYCoord = 0.0; double newZCoord = 0.0; double& currXCoord = GA.x(v); double& currYCoord = GA.y(v); double totalWeight = 0; for (node w : G.nodes) { if (v == w) { continue; } // calculate euclidean distance between both points double xDiff = currXCoord - GA.x(w); double yDiff = currYCoord - GA.y(w); double zDiff = (GA.attributes() & GraphAttributes::threeD) ? GA.z(v) - GA.z(w) : 0.0; double euclideanDist = sqrt(xDiff * xDiff + yDiff * yDiff + zDiff * zDiff); // get the weight double weight = weights[v][w]; // get the desired distance double desDistance = shortestPathMatrix[v][w]; // reset the voted x coordinate // if x is not fixed if (!m_fixXCoords) { double voteX = GA.x(w); if (euclideanDist != 0) { // calc the vote voteX += desDistance * (currXCoord - voteX) / euclideanDist; } // add the vote newXCoord += weight * voteX; } // reset the voted y coordinate // y is not fixed if (!m_fixYCoords) { double voteY = GA.y(w); if (euclideanDist != 0) { // calc the vote voteY += desDistance * (currYCoord - voteY) / euclideanDist; } newYCoord += weight * voteY; } if (GA.attributes() & GraphAttributes::threeD) { // reset the voted z coordinate // z is not fixed if (!m_fixZCoords) { double voteZ = GA.z(w); if (euclideanDist != 0) { // calc the vote voteZ += desDistance * (GA.z(v) - voteZ) / euclideanDist; } newZCoord += weight * voteZ; } } // sum up the weights totalWeight += weight; } // update the positions if (totalWeight != 0) { if (!m_fixXCoords) { currXCoord = newXCoord / totalWeight; } if (!m_fixYCoords) { currYCoord = newYCoord / totalWeight; } if (GA.attributes() & GraphAttributes::threeD) { if (!m_fixZCoords) { GA.z(v) = newZCoord / totalWeight; } } } } }