The following examples will show how to use the library for rewriting port graphs:
Some examples:
A snow flake example consists in replacing an edge by a multi-edge as follow:
The translation in port graph module is has follow:
The pattern graph to search in the large graph contains :
- 2 nodes a,b
- 2 ports qa, qb with tag {+} port qa port and with tag {-} for qb port
- 3 edges [a,qa] [qa,qb] [qb,b]
The replacment transformer graph contains:
- 3 nodes i,j,k
- 6 ports pi,qi,qj,qj,pk,qk with respectivly tags +,-,+,-,+,-,+,-
- 8 edges [pi,i],[i,qi],[qi,pj],[pj,j],[j,qj],[qj,pk],[pk,k],[k,qk]
The coordinates of the new nodes i,j,k has defined has follow:
- I=(2/3)A+(1/3)B
- K=(1/3)A+(2/3)B
- J=(1/2)(A+B)+(sqrt(3)/6)(-Arot+Brot) where Arot=(-Y,X,Z) when A=(x,y,z)
The rules are as follow:
- erase edge [qa,qb] from pattern graph
- add edges [qa,pi] [qb,qk] between pattern & transformer graph
The large graph is a triangle which contains:
- 3 nodes A(0,sqrt(2),0),B(1,0,0),C(-1,0,0)
- 6 associated ports qA,qB,rb,rc,pc,pa with tags +,-,+,-,+,-
The results obtains after 8 iterations is given as follow:
To simulate this example, 2 classes have to been created:
The GPM_2DSnowGraph::createPatternsFunctions which create a patterns functions has to be sepcialized: it creates pattern graph, transformer graph, GPM_Snow2DFunction. The code is like this:
SP::GPM_PortGraph patternGraph=createPatternGraph(pA,pB);
SP::GPM_PortGraph transformerGraph=createTransformerGraph(tA,tB);
patternF->setPatternGraph(patternGraph);
patternF->setTransformerGraph(transformerGraph);
patternF->addPEdgeToRemove(pA,pB);
patternF->addPTEdgeToAdd(pA,tA);
patternF->addPTEdgeToAdd(pB,tB);
patternFunctions.clear();
patternFunctions.add(patternF);
return true;
}
The method GPM_PatternFunction::addPEdgeToRemove adds a marker to remove the mapped pattern edge in the large graph
The method GPM_PatternFunction::addPTEdgeToAdd adds an edge in the large graph between mapped pattern graph and the copied transformer graph in the large graph
The method GPM_2DSnowGraph::createTransformerGraph (similarly GPM_2DSnowGraph::createPatternGraph) creates a graph
int index=-1;
iid=patternTransformed->addPort("-",++index);tA=iid;
iid=patternTransformed->addVertex(++index);
iid=patternTransformed->addPort("+",++index);
iid=patternTransformed->addPort("-",++index);
iid=patternTransformed->addVertex(++index);
iid=patternTransformed->addPort("+",++index);
iid=patternTransformed->addPort("-",++index);
iid=patternTransformed->addVertex(++index);
iid=patternTransformed->addPort("+",++index);tB=iid;
index=0;
patternTransformed->addEdgeFromIds(0,1);
patternTransformed->addEdgeFromIds(1,2);
patternTransformed->addEdgeFromIds(2,3);
patternTransformed->addEdgeFromIds(3,4);
patternTransformed->addEdgeFromIds(4,5);
patternTransformed->addEdgeFromIds(5,6);
patternTransformed->addEdgeFromIds(6,7);
patternTransformed->addEdgeFromIds(7,8);
return patternTransformed;
}
To define the new position of nodes, the methode GPM_PatternFunction::updateStates has to be specialized. it defined the new coordinates of the copied transformer graph
const vector<tVertexIID>& mappingP2L,
const map<tVertexIID,tVertexIID>& mappingT2L) {
SP::GPM_Node node;
const GPM_Graph& patternGraph=getPatternGraph();
const GPM_Graph& transformerGraph=getTransformerGraph();
map<tVertexIID,tVertexIID>::const_iterator mappingT2LIter;
if (node.get()==
null)
return false;
const tReal *X=node->getCoordinates();
tReal Xrot[]={-X[1],X[0],X[2]};
if (node.get()==
null)
return false;
const tReal *Y=node->getCoordinates();
tReal Yrot[]={-Y[1],Y[0],Y[2]};
int k=0;
for (k=0;k<3;k++) coord[k]=(2./3.)*X[k]+(1./3.)*Y[k];
mappingT2LIter=mappingT2L.find(iid);
if (mappingT2LIter!=mappingT2L.end()) {
}
for (k=0;k<3;k++) {
coord[k]=0.5*(X[k]+Y[k]);
coord[k]+=(sqrt(3.)/6.)*(-Xrot[k]+Yrot[k]);
}
mappingT2LIter=mappingT2L.find(iid);
if (mappingT2LIter!=mappingT2L.end()) {
}
for (k=0;k<3;k++) coord[k]=(1./3.)*X[k]+(2./3.)*Y[k];
mappingT2LIter=mappingT2L.find(iid);
if (mappingT2LIter!=mappingT2L.end()) {
}
return succeeds;
}
Note that the nodes & ports are vertices so a special care needs to take the nodes at the right index.