// assumes, that the Graphs of MultilevelGraph and GA are the same, not copies! void MultilevelGraph::exportAttributesSimple(GraphAttributes &GA) const { OGDF_ASSERT(&(GA.constGraph()) == m_G); prepareGraphAttributes(GA); for(node v : m_G->nodes) { GA.x(v) = m_GA->x(v); GA.y(v) = m_GA->y(v); //TODO: Check what this w,h computation does double w = GA.width(v); double h = GA.height(v); if(w > 0 || h > 0) { double factor = m_radius[v] / sqrt(w*w + h*h) * 2.0f; w *= factor; h *= factor; } else { w = h = m_radius[v] * sqrt(2.0f); } GA.width(v) = w; GA.height(v) = h; GA.weight(v) = m_reverseNodeMergeWeight[v->index()]; } for(edge e : m_G->edges) { GA.doubleWeight(e) = m_weight[e]; } }
void MultilevelGraph::importAttributesSimple(const GraphAttributes &GA) { OGDF_ASSERT(&(GA.constGraph()) == m_G); m_avgRadius = 0.0; for(node v : m_G->nodes) { double w = GA.width(v); double h = GA.height(v); if(w > 0 || h > 0) { m_radius[v] = sqrt(w*w + h*h) / 2.0f; } else { m_radius[v] = 1.0f; } m_avgRadius += m_radius[v]; m_GA->x(v) = GA.x(v); m_GA->y(v) = GA.y(v); m_GA->width(v) = GA.width(v); m_GA->height(v) = GA.height(v); } m_avgRadius /= m_G->numberOfNodes(); for(edge e : m_G->edges) { m_weight[e] = GA.doubleWeight(e); } }
void FastMultipoleMultilevelEmbedder::computeAutoEdgeLength(const GraphAttributes& GA, EdgeArray<float>& edgeLength, float factor) { for(edge e : GA.constGraph().edges) { node v = e->source(); node w = e->target(); float radius_v = (float)sqrt(GA.width(v)*GA.width(v) + GA.height(v)*GA.height(v)) * 0.5f; float radius_w = (float)sqrt(GA.width(w)*GA.width(w) + GA.height(w)*GA.height(w)) * 0.5f; float sum = radius_v + radius_w; if (OGDF_GEOM_ET.equal(sum, (float) 0)) sum = 1.0; edgeLength[e] = factor*(sum); } }
//the vertices with degree zero are placed below all other vertices on a horizontal // line centered with repect to the rest of the drawing void DavidsonHarel::placeIsolatedNodes(GraphAttributes &AG) const { double minX = 0.0; double minY = 0.0; double maxX = 0.0; if (!m_nonIsolatedNodes.empty()) { //compute a rectangle that includes all non-isolated vertices node vFirst = m_nonIsolatedNodes.front(); minX = AG.x(vFirst); minY = AG.y(vFirst); maxX = minX; double maxY = minY; for (node v : m_nonIsolatedNodes) { double xVal = AG.x(v); double yVal = AG.y(v); double halfHeight = AG.height(v) / 2.0; double halfWidth = AG.width(v) / 2.0; if (xVal - halfWidth < minX) minX = xVal - halfWidth; if (xVal + halfWidth > maxX) maxX = xVal + halfWidth; if (yVal - halfHeight < minY) minY = yVal - halfHeight; if (yVal + halfHeight > maxY) maxY = yVal + halfHeight; } } // compute the width and height of the largest isolated node List<node> isolated; const Graph &G = AG.constGraph(); double maxWidth = 0; double maxHeight = 0; for (node v : G.nodes) if (v->degree() == 0) { isolated.pushBack(v); if (AG.height(v) > maxHeight) maxHeight = AG.height(v); if (AG.width(v) > maxWidth) maxWidth = AG.width(v); } // The nodes are placed on a line in the middle under the non isolated vertices. // Each node gets a box sized 2 maxWidth. double boxWidth = 2.0*maxWidth; double commonYCoord = minY - (1.5*maxHeight); double XCenterOfDrawing = minX + ((maxX - minX) / 2.0); double startXCoord = XCenterOfDrawing - 0.5*(isolated.size()*boxWidth); double xcoord = startXCoord; for (node v : isolated) { AG.x(v) = xcoord; AG.y(v) = commonYCoord; xcoord += boxWidth; } }
void RadialTreeLayout::ComputeDiameters(GraphAttributes &AG) { const Graph &G = AG.constGraph(); m_diameter.init(G); m_nodes.init(m_numLevels); m_width.init(m_numLevels); m_width.fill(0); for(node v : G.nodes) { int i = m_level[v]; m_nodes[i].pushBack(v); double w = AG.width(v); double h = AG.height(v); m_diameter[v] = sqrt(w*w+h*h); double m = max(w, h); m = max(m, sqrt(w*w+h*h)); if(m_diameter[v] > m_width[i]) m_width[i] = m_diameter[v]; } }
void FastMultipoleEmbedder::call(GraphAttributes &GA) { EdgeArray<float> edgeLength(GA.constGraph()); NodeArray<float> nodeSize(GA.constGraph()); for(node v : GA.constGraph().nodes) { nodeSize[v] = (float)sqrt(GA.width(v)*GA.width(v) + GA.height(v)*GA.height(v)) * 0.5f; } for(edge e : GA.constGraph().edges) { edgeLength[e] = nodeSize[e->source()] + nodeSize[e->target()]; } call(GA, edgeLength, nodeSize); }
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; }
void DominanceLayout::compact(const UpwardPlanRep &UPR, GraphAttributes &GA) { double maxNodeSize = 0; for(node v : GA.constGraph().nodes) { if (GA.width(v) > maxNodeSize || GA.height(v) > maxNodeSize) maxNodeSize = max(GA.width(v), GA.height(v)); } int gridDist = m_grid_dist; if (gridDist < maxNodeSize+1) gridDist = (int) maxNodeSize+1; xCoord.init(UPR); yCoord.init(UPR); //ASSIGN X COORDINATE OGDF_ASSERT(!xNodes.empty()); node v = xNodes.popFrontRet(); xCoord[v] = 0; while (!xNodes.empty()) { node u = xNodes.popFrontRet(); if ( (yPreCoord[v] > yPreCoord[u]) || (firstout[v] == lastout[v] && firstin[u] == lastin[u] && m_L <= m_R)) { xCoord[u] = xCoord[v] + gridDist; } else xCoord[u] = xCoord[v]; v = u; } //ASSIGN Y COORDINATE OGDF_ASSERT(!yNodes.empty()); v = yNodes.popFrontRet(); yCoord[v] = 0; while (!yNodes.empty()) { node u = yNodes.popFrontRet(); if ( (xPreCoord[v] > xPreCoord[u]) || (firstout[v] == lastout[v] && firstin[u] == lastin[u] && m_L > m_R)) { yCoord[u] = yCoord[v] + gridDist; } else yCoord[u] = yCoord[v]; v = u; } }
void MultilevelGraph::importAttributes(const GraphAttributes &GA) { OGDF_ASSERT(GA.constGraph().numberOfNodes() == m_G->numberOfNodes()); OGDF_ASSERT(GA.constGraph().numberOfEdges() == m_G->numberOfEdges()); m_avgRadius = 0.0; std::vector<node> tempNodeAssociations; const Graph &cG = GA.constGraph(); tempNodeAssociations.resize(cG.maxNodeIndex()+1, nullptr); for(node v : cG.nodes) { tempNodeAssociations[v->index()] = v; } for(node v : m_G->nodes) { double w = GA.width(tempNodeAssociations[m_nodeAssociations[v]]); double h = GA.height(tempNodeAssociations[m_nodeAssociations[v]]); if(w > 0 || h > 0) { m_radius[v] = sqrt(w*w + h*h) / 2.0f; } else { m_radius[v] = 1.0f; } m_avgRadius += m_radius[v]; m_GA->x(v) = GA.x(tempNodeAssociations[m_nodeAssociations[v]]); m_GA->y(v) = GA.y(tempNodeAssociations[m_nodeAssociations[v]]); m_GA->width(v) = GA.width(tempNodeAssociations[m_nodeAssociations[v]]); m_GA->height(v) = GA.height(tempNodeAssociations[m_nodeAssociations[v]]); } m_avgRadius /= m_G->numberOfNodes(); std::vector<edge> tempEdgeAssociations; tempEdgeAssociations.resize(cG.maxEdgeIndex()+1, nullptr); for(edge e : cG.edges) { tempEdgeAssociations[e->index()] = e; } for(edge e : m_G->edges) { m_weight[e] = GA.doubleWeight(tempEdgeAssociations[m_edgeAssociations[e]]); } }
void TutteLayout::call(GraphAttributes &AG) { const Graph &G = AG.constGraph(); List<node> fixedNodes; List<DPoint> positions; double diam = sqrt((m_bbox.width()) * (m_bbox.width()) + (m_bbox.height()) * (m_bbox.height())); // handle graphs with less than two nodes switch (G.numberOfNodes()) { case 0: return; case 1: node v = G.firstNode(); DPoint center(0.5 * m_bbox.width(),0.5 * m_bbox.height()); center = center + m_bbox.p1(); AG.x(v) = center.m_x; AG.y(v) = center.m_y; return; } // increase radius to have no overlap on the outer circle node v = G.firstNode(); double r = diam/2.8284271; int n = G.numberOfNodes(); double nodeDiam = 2.0*sqrt((AG.width(v)) * (AG.width(v)) + (AG.height(v)) * (AG.height(v))); if(r<nodeDiam/(2*sin(2*Math::pi/n))) { r=nodeDiam/(2*sin(2*Math::pi/n)); m_bbox = DRect (0.0, 0.0, 2*r, 2*r); } setFixedNodes(G,fixedNodes,positions,r); doCall(AG,fixedNodes,positions); }
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); //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)); } m_secondaryLayout.get().call(cGA); //copy layout information back into GA forall_nodes(v, GC) { node w = GC.original(v); if (w != 0) GA.x(w) = cGA.x(v); GA.y(w) = cGA.y(v); } }
void MultilevelGraph::exportAttributes(GraphAttributes &GA) const { OGDF_ASSERT(GA.constGraph().numberOfNodes() == m_G->numberOfNodes()); OGDF_ASSERT(GA.constGraph().numberOfEdges() == m_G->numberOfEdges()); prepareGraphAttributes(GA); std::vector<node> tempNodeAssociations; const Graph &cG = GA.constGraph(); tempNodeAssociations.resize(cG.maxNodeIndex()+1, nullptr); for(node v : cG.nodes) { tempNodeAssociations[v->index()] = v; } for(node v : m_G->nodes) { GA.x(tempNodeAssociations[m_nodeAssociations[v]]) = m_GA->x(v); GA.y(tempNodeAssociations[m_nodeAssociations[v]]) = m_GA->y(v); double w = GA.width(tempNodeAssociations[m_nodeAssociations[v]]); double h = GA.height(tempNodeAssociations[m_nodeAssociations[v]]); if(w > 0 || h > 0) { double factor = m_radius[v] / sqrt(w*w + h*h) * 2.0f; w *= factor; h *= factor; } else { w = h = m_radius[v] * sqrt(2.0f); } GA.width(tempNodeAssociations[m_nodeAssociations[v]]) = w; GA.height(tempNodeAssociations[m_nodeAssociations[v]]) = h; GA.weight(tempNodeAssociations[m_nodeAssociations[v]]) = m_reverseNodeMergeWeight[v->index()]; } std::vector<edge> tempEdgeAssociations; tempEdgeAssociations.resize(cG.maxEdgeIndex()+1, nullptr); for(edge e :cG.edges) { tempEdgeAssociations[e->index()] = e; } for(edge e : m_G->edges) { GA.doubleWeight(tempEdgeAssociations[m_edgeAssociations[e]]) = m_weight[e]; } }
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); }
inline void FMMMLayout :: import_NodeAttributes(const Graph& G, GraphAttributes& GA, NodeArray<NodeAttributes>& A) { node v; DPoint position; forall_nodes(v,G) { position.m_x = GA.x(v); position.m_y = GA.y(v); A[v].set_NodeAttributes(GA.width(v),GA.height(v),position,NULL,NULL); }
void GridLayoutModule::mapGridLayout(const Graph &G, GridLayout &gridLayout, GraphAttributes &AG) { double maxWidth = 0; // maximum width of columns and rows; double yMax = 0; node v; forall_nodes(v,G) { if (AG.width (v) > maxWidth) maxWidth = AG.width (v); if (AG.height(v) > maxWidth) maxWidth = AG.height(v); if (gridLayout.y(v) > yMax) yMax = gridLayout.y(v); } maxWidth += m_separation; // set position of nodes forall_nodes(v,G) { AG.x(v) = gridLayout.x(v) * maxWidth; AG.y(v) = (yMax - gridLayout.y(v)) * maxWidth; }
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 << "]"; }
void FastMultipoleMultilevelEmbedder::initFinestLevel(GraphAttributes &GA, const EdgeArray<float>& edgeLength) { #if 0 NodeArray<float> perimeter(GA.constGraph(), 0.0); #endif for(node v : GA.constGraph().nodes) { GalaxyMultilevel::LevelNodeInfo& nodeInfo = (*(m_pFinestLevel->m_pNodeInfo))[v]; nodeInfo.mass = 1.0; float r = (float)sqrt(GA.width(v)*GA.width(v) + GA.height(v)*GA.height(v)) * 0.5f; nodeInfo.radius = r; } for(edge e : GA.constGraph().edges) { GalaxyMultilevel::LevelEdgeInfo& edgeInfo = (*(m_pFinestLevel->m_pEdgeInfo))[e]; node v = e->source(); node w = e->target(); GalaxyMultilevel::LevelNodeInfo& vNodeInfo = (*(m_pFinestLevel->m_pNodeInfo))[v]; GalaxyMultilevel::LevelNodeInfo& wNodeInfo = (*(m_pFinestLevel->m_pNodeInfo))[w]; edgeInfo.length = (vNodeInfo.radius + wNodeInfo.radius) + edgeLength[e]; } }
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(); } }
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 << "]"; }
void createDocument(GraphAttributes attr, pugi::xml_document &doc, GraphIO::SVGSettings *settings = nullptr, bool reassignPositions = true) { std::ostringstream write; if(reassignPositions) { int i = 0; for(node v : attr.constGraph().nodes) { attr.x(v) = attr.y(v) = i++ * 100; attr.width(v) = attr.height(v) = 10; } } if(settings == nullptr) { GraphIO::drawSVG(attr, write); } else { GraphIO::drawSVG(attr, write, *settings); } pugi::xml_parse_result result = doc.load_string(write.str().c_str()); AssertThat((bool) result, IsTrue()); }
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
//************************************************************* // 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); } } }
void SpringEmbedderFR::call(GraphAttributes &AG) { const Graph &G = AG.constGraph(); if(G.empty()) return; // all edges straight-line AG.clearAllBends(); GraphCopy GC; GC.createEmpty(G); // compute connected component of G NodeArray<int> component(G); int numCC = connectedComponents(G,component); // intialize the array of lists of nodes contained in a CC Array<List<node> > nodesInCC(numCC); node v; forall_nodes(v,G) nodesInCC[component[v]].pushBack(v); EdgeArray<edge> auxCopy(G); Array<DPoint> boundingBox(numCC); int i; for(i = 0; i < numCC; ++i) { GC.initByNodes(nodesInCC[i],auxCopy); GraphCopyAttributes AGC(GC,AG); node vCopy; forall_nodes(vCopy, GC) { node vOrig = GC.original(vCopy); AGC.x(vCopy) = AG.x(vOrig); AGC.y(vCopy) = AG.y(vOrig); } // original if (initialize(GC, AGC) == true) { for(int i = 1; i <= m_iterations; i++) mainStep(GC, AGC); } cleanup(); // end original node vFirst = GC.firstNode(); double minX = AGC.x(vFirst), maxX = AGC.x(vFirst), minY = AGC.y(vFirst), maxY = AGC.y(vFirst); forall_nodes(vCopy,GC) { node v = GC.original(vCopy); AG.x(v) = AGC.x(vCopy); AG.y(v) = AGC.y(vCopy); if(AG.x(v)-AG.width (v)/2 < minX) minX = AG.x(v)-AG.width(v) /2; if(AG.x(v)+AG.width (v)/2 > maxX) maxX = AG.x(v)+AG.width(v) /2; if(AG.y(v)-AG.height(v)/2 < minY) minY = AG.y(v)-AG.height(v)/2; if(AG.y(v)+AG.height(v)/2 > maxY) maxY = AG.y(v)+AG.height(v)/2; }
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 }
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 SpringEmbedderFRExact::call(GraphAttributes &AG) { const Graph &G = AG.constGraph(); if(G.empty()) return; // all edges straight-line AG.clearAllBends(); ArrayGraph component(AG); component.m_useNodeWeight = m_useNodeWeight; EdgeArray<edge> auxCopy(G); Array<DPoint> boundingBox(component.numberOfCCs()); int i; for(i = 0; i < component.numberOfCCs(); ++i) { component.initCC(i); if (component.numberOfNodes() >= 2) { initialize(component); #ifdef OGDF_SSE3_EXTENSIONS if(System::cpuSupports(cpufSSE3)) mainStep_sse3(component); else #endif mainStep(component); } double minX, maxX, minY, maxY; minX = maxX = component.m_x[0]; minY = maxY = component.m_y[0]; for(int vCopy = 0; vCopy < component.numberOfNodes(); ++vCopy) { node v = component.original(vCopy); AG.x(v) = component.m_x[vCopy]; AG.y(v) = component.m_y[vCopy]; if(AG.x(v)-AG.width (v)/2 < minX) minX = AG.x(v)-AG.width(v) /2; if(AG.x(v)+AG.width (v)/2 > maxX) maxX = AG.x(v)+AG.width(v) /2; if(AG.y(v)-AG.height(v)/2 < minY) minY = AG.y(v)-AG.height(v)/2; if(AG.y(v)+AG.height(v)/2 > maxY) maxY = AG.y(v)+AG.height(v)/2; } minX -= m_minDistCC; minY -= m_minDistCC; for(int vCopy = 0; vCopy < component.numberOfNodes(); ++vCopy) { node v = component.original(vCopy); AG.x(v) -= minX; AG.y(v) -= minY; } boundingBox[i] = DPoint(maxX - minX, maxY - minY); } Array<DPoint> offset(component.numberOfCCs()); TileToRowsCCPacker packer; packer.call(boundingBox,offset,m_pageRatio); // The arrangement is given by offset to the origin of the coordinate // system. We still have to shift each node and edge by the offset // of its connected component. for(i = 0; i < component.numberOfCCs(); ++i) { const SList<node> &nodes = component.nodesInCC(i); const double dx = offset[i].m_x; const double dy = offset[i].m_y; // iterate over all nodes in ith CC for(node v : nodes) { AG.x(v) += dx; AG.y(v) += dy; } } }
//************************************************************* // 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
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"; } } }
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; }
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