GraphSize OperationDrawer::drawClass(DiagramDrawer &drawer, const OperationClass &node, const OperationDrawOptions & /*options*/, bool draw) { GraphPoint startpos = node.getPosition(); const ModelType *type = node.getType(); OovStringRef const typeName = type->getName(); int rectx = 0; int recty = 0; const ModelClassifier *classifier = type->getClass(); if(classifier) { if(draw) { drawer.groupText(true, false); } OovStringVec strs; std::vector<GraphPoint> positions; strs.push_back(typeName); splitStrings(strs, 30, 40); for(auto const &str : strs) { recty += mCharHeight + (mPad * 2); positions.push_back(GraphPoint(startpos.x+mPad, startpos.y + recty - mPad)); int curx = static_cast<int>(drawer.getTextExtentWidth(str)) + mPad*2; if(curx > rectx) rectx = curx; } if(draw) { drawer.groupShapes(true, Color(0,0,0), Color(245,245,255)); drawer.drawRect(GraphRect(startpos.x, startpos.y, rectx, recty)); drawer.groupShapes(false, Color(0,0,0), Color(245,245,255)); for(size_t i=0; i<strs.size(); i++) { drawer.drawText(positions[i], strs[i]); } drawer.groupText(false, false); } } return GraphSize(rectx, recty); }
GraphSize OperationDrawer::drawOperationNoText(DiagramDrawer &drawer, GraphPoint pos, OperationDefinition &operDef, const OperationGraph &graph, const OperationDrawOptions &options, std::set<const OperationDefinition*> &drawnOperations, std::vector<DrawString> &drawStrings, bool draw, int callDepth) { GraphPoint startpos = pos; // Add space between bottom of class and operation name int starty = startpos.y+(mPad*2); int y=starty; size_t sourceIndex = operDef.getOperClassIndex(); int arrowLen = mCharHeight * 7 / 10; std::vector<int> condStartPosY; drawnOperations.insert(&operDef); const OperationClass &cls = graph.getClass(sourceIndex); if(callDepth == 0) { // Reinit all polys to initial conditions. mLifelinePolygons.clear(); mLifelinePolygons.resize(graph.getClasses().size()); } BlockPolygon &poly = mLifelinePolygons[sourceIndex]; poly.setup(cls.getLifelinePosX(), mPad); if(!graph.isOperCalled(operDef)) { // Show starting operation operDef.setRect(GraphPoint(cls.getPosition().x, y), GraphSize(mCharHeight*50, mCharHeight+mPad)); y += mCharHeight; drawStrings.push_back(DrawString(GraphPoint( cls.getPosition().x, y), operDef.getName())); // Add space between operation name and called operations. y += (mPad * 2); int lineY = y + mPad*2; if(draw) { drawCall(drawer, GraphPoint(cls.getPosition().x, lineY), GraphPoint(cls.getLifelinePosX(), lineY), operDef.isConst(), arrowLen); } } for(const auto &stmt : operDef.getStatements()) { int condOffset = poly.getDepth() * mPad; switch(stmt->getStatementType()) { case ST_Call: { OperationCall *call = stmt->getCall(); size_t targetIndex = call->getOperClassIndex(); int lineY = y + mCharHeight + mPad*2; int sourcex = cls.getLifelinePosX(); sourcex += condOffset; const OperationClass &targetCls = graph.getClass(targetIndex); int targetx = targetCls.getLifelinePosX(); if(targetIndex == NO_INDEX) { // Handle [else] // int len = mCharHeight*3; // mDrawer.drawLine(GraphPoint(sourcex, lineY), // GraphPoint(sourcex+len, lineY), call->isConst()); } else if(targetIndex != sourceIndex) { if(draw) { drawCall(drawer, GraphPoint(sourcex, lineY), GraphPoint(targetx, lineY), call->isConst(), arrowLen); } } else { // Draw line back to same class int len = mCharHeight*3; int height = 3; if(draw) { drawer.drawLine(GraphPoint(sourcex, lineY), GraphPoint(sourcex+len, lineY), call->isConst()); drawer.drawLine(GraphPoint(sourcex+len, lineY), GraphPoint(sourcex+len, lineY+height)); drawer.drawLine(GraphPoint(sourcex, lineY+height), GraphPoint(sourcex+len, lineY+height), call->isConst()); } y += height; } int textX = (sourceIndex < targetIndex) ? cls.getLifelinePosX() : targetCls.getLifelinePosX(); GraphPoint callPos(textX+condOffset+mPad, y+mCharHeight); drawStrings.push_back(DrawString(callPos, call->getName())); call->setRect(GraphPoint(callPos.x, callPos.y-mCharHeight), GraphSize(mCharHeight*50, mCharHeight+mPad)); y += mCharHeight*2; // Draw child definition. OperationDefinition *childDef = graph.getOperDefinition(*call); if(childDef) { // poly.startChildBlock(condDepth, y); if(drawnOperations.find(childDef) == drawnOperations.end()) { poly.incDepth(y); GraphSize childSize = drawOperationNoText(drawer, GraphPoint(pos.x, y), *childDef, graph, options, drawnOperations, drawStrings, draw, callDepth+1); y += childSize.y + mPad * 2; poly.decDepth(y); } else { // This draws a rectangle to signify that it is defined // elsewhere in the diagram. GraphRect rect(targetx + mPad*2, callPos.y + mPad*2, mCharHeight+mPad, mCharHeight+mPad); if(draw) { drawer.drawRect(rect); } y += mCharHeight+mPad; } // poly.endChildBlock(condDepth, y); } } break; case ST_VarRef: { OperationVarRef *ref = stmt->getVarRef(); size_t targetIndex = ref->getOperClassIndex(); int lineY = y + mCharHeight + mPad*2; int sourcex = cls.getLifelinePosX(); sourcex += condOffset; const OperationClass &targetCls = graph.getClass(targetIndex); int targetx = targetCls.getLifelinePosX(); if(targetIndex == NO_INDEX) { int len = mCharHeight*3; if(draw) { drawer.drawLine(GraphPoint(sourcex, lineY), GraphPoint(sourcex+len, lineY), ref->isConst()); } } else if(targetIndex != sourceIndex) { if(draw) { drawCall(drawer, GraphPoint(sourcex, lineY), GraphPoint(targetx, lineY), ref->isConst(), arrowLen); } } else { // Draw line back to same class int len = mCharHeight*3; int height = 3; if(draw) { drawer.drawLine(GraphPoint(sourcex, lineY), GraphPoint(sourcex+len, lineY), ref->isConst()); drawer.drawLine(GraphPoint(sourcex+len, lineY), GraphPoint(sourcex+len, lineY+height)); drawer.drawLine(GraphPoint(sourcex, lineY+height), GraphPoint(sourcex+len, lineY+height), ref->isConst()); } y += height; } int textX = (sourceIndex < targetIndex) ? cls.getLifelinePosX() : targetCls.getLifelinePosX(); GraphPoint callPos(textX+condOffset+mPad, y+mCharHeight); if(draw) { drawStrings.push_back(DrawString(callPos, ref->getName())); } ref->setRect(GraphPoint(callPos.x, callPos.y-mCharHeight), GraphSize(mCharHeight*50, mCharHeight+mPad)); y += mCharHeight*2; } break; case ST_OpenNest: { GraphPoint lifePos(cls.getLifelinePosX()+condOffset+ mPad, y+mCharHeight); const OperationNestStart *cond = stmt->getNestStart(); if(draw) { drawStrings.push_back(DrawString(lifePos, cond->getExpr())); } condStartPosY.push_back(y); y += mCharHeight*2; poly.incDepth(y); } break; case ST_CloseNest: { poly.decDepth(y); } break; } } if(callDepth == 0) { for(auto &poly : mLifelinePolygons) { poly.finishBlock(); if(draw) { drawer.drawPoly(poly, Color(245,245,255)); } } } return GraphSize(0, y - startpos.y); }
int main(int argc, char **argv) { Parameters *parameters; ULONG numLabels; Graph *g1; Graph *g2; Graph *g2compressed; InstanceList *instanceList; ULONG numInstances; ULONG subSize, graphSize, compressedSize; double subDL, graphDL, compressedDL; double value; Label label; parameters = GetParameters(argc, argv); g1 = ReadGraph(argv[argc - 2], parameters->labelList, parameters->directed); g2 = ReadGraph(argv[argc - 1], parameters->labelList, parameters->directed); instanceList = FindInstances(g1, g2, parameters); numInstances = CountInstances(instanceList); printf("Found %lu instances.\n\n", numInstances); g2compressed = CompressGraph(g2, instanceList, parameters); // Compute and print compression-based measures subSize = GraphSize(g1); graphSize = GraphSize(g2); compressedSize = GraphSize(g2compressed); value = ((double) graphSize) / (((double) subSize) + ((double) compressedSize)); printf("Size of graph = %lu\n", graphSize); printf("Size of substructure = %lu\n", subSize); printf("Size of compressed graph = %lu\n", compressedSize); printf("Value = %f\n\n", value); // Compute and print MDL based measures numLabels = parameters->labelList->numLabels; subDL = MDL(g1, numLabels, parameters); graphDL = MDL(g2, numLabels, parameters); numLabels++; // add one for new "SUB" vertex label if ((parameters->allowInstanceOverlap) && (InstancesOverlap(instanceList))) numLabels++; // add one for new "OVERLAP" edge label compressedDL = MDL(g2compressed, numLabels, parameters); // add extra bits to describe where external edges connect to instances compressedDL += ExternalEdgeBits(g2compressed, g1, numInstances); value = graphDL / (subDL + compressedDL); printf("DL of graph = %f\n", graphDL); printf("DL of substructure = %f\n", subDL); printf("DL of compressed graph = %f\n", compressedDL); printf("Value = %f\n\n", value); if (parameters->outputToFile) { // first, actually add "SUB" and "OVERLAP" labels label.labelType = STRING_LABEL; label.labelValue.stringLabel = SUB_LABEL_STRING; StoreLabel(& label, parameters->labelList); label.labelValue.stringLabel = OVERLAP_LABEL_STRING; StoreLabel(& label, parameters->labelList); parameters->posGraph = g2compressed; WriteGraphToDotFile(parameters->outFileName, parameters); printf("Compressed graph written to dot file %s\n", parameters->outFileName); } FreeGraph(g2compressed); FreeInstanceList(instanceList); FreeGraph(g1); FreeGraph(g2); FreeParameters(parameters); return 0; }