Graph A graph for GeoGraphy

Inherits from: Object

Graph is the class devoted to representating all the information related to graph. As a graph can be disconnected (i.e. subdivided in subgraphs), there is not necessity of having more than one instace of graph.

See also: GeoGraphyIntro

Data structure

Substantially the class adds some functionality to an IdentityDictionary named "graphDict", which represents all the data relative to the graph.

Note: GUIs are always deferred, so you can use SystemClock in routines involving graphics.

Creation / Class Methods

*new (graphDict)

Create a new Graph

graphDict - a graphDict can be provided, otherwise an empty one is created. Default value is nil.

(

// create a graph

g = Graph.new;

g.graphDict.postln ; // empty

)

Accessing Instance and Class Variables

nv

Represents the number of vertices in the graph. It is updated by graph editing methods.

Starts from 1.

ne

Represents the number of edges in the graph. It is updated by graph editing methods.

Starts from 1.

graphDict_(arg1)

graphDict

It is and IdentityDictionary representing the graph structure.

A graph is an IdentityDictionary following this format:

{vID: [x, y, vDur, vLabel, vOpts, [end, eDur, eID, eOpts], ...etc], etc:...}

where:

vID: ID of a vertex;

x, y: its position

vDur: a duration associated to the vertex

vLabel: a label associated to the vertex

vOpts: usable to store optional infos related to the vertex. If you need more values, use an array.

[...]: each following array represents an edge starting from the vertex

this means: n arrays --> n edges from vID

The format of an edge array is:

end: the end vertex

eDur: the duration of the edge

eID: an ID associated to the edge

eOpts: usable to store optional infos related to the edge

Operating on the graph

The following are the methods provided to access/modify the graph.

addVertex (x, y, dur, label, opts, vID)

Add a vertex to the graph and updates nv and ne

x - the x position of the vertex. Default value is nil.

y - the y position of the vertex. Default value is nil.

dur - a duration associated vertex. Note that this is related to the vertex, not to the edges. Default value is 0.

label - a string allowing to meaningfully label the vertes . Default value is "". As you typically don't control vID directly, label is the place where you can differentiate explicitly vertices.

opts - and optional value where one can store other important information. Default value is nil.

vID - the vertex id. You typically leave it to its default value nil. In this case aan id is provided automatically. Set it only if you really know what you ar doing.

(

// two placements

g = Graph.new ;

40.do({|i| g.addVertex(i*20+50, i*20, 0, "test"++i)});

g.plot ;

g = Graph.new ;

500.do({|i| g.addVertex(500.rand+300, 500.rand+150, 0, "test"++i)});

g.plot ;

)

changeVertexPosition (vID, x, y)

Allow changing the position of a vertex by providing its viD and new coordinates.

vID - the vID. Default value is nil.

x - new x. Default value is nil.

y - new y. Default value is nil.

(

g = Graph.new.addVertex(500, 500, 0, "bump") ;

p = Painter.new(g) ; // p is registered to g and reacts to its changements

Routine({

100.do({ arg i ;

g.changeVertexPosition(1, 1000-(i*9), 700-(i*5)) ;

0.05.wait ;

})

}).play(SystemClock)

)

addEdge (start, end, dur, options)

Short prose description of method.

start - the starting vertex ID. Default value is nil.

end - the ending vertex ID. Default value is nil.

dur - the duration o fthe edge. Default value is nil.

options - an array of desidered options to be associated with edge. Default value is nil.

(

g = Graph.new.addVertex(1000.rand, 700.rand, 0, 64.asAscii) ;

p = Painter.new(g) ;

// nv starts from 1 and it has already been increased. So now it's 2

g.nv.postln ;

Routine({

63.do({ arg i ;

l = (65+i).asAscii ;

g.addVertex(1000.rand, 700.rand, 0, l) ;

// nv has been increased

g.addEdge(g.nv-2, g.nv-1, 1.0.rand) ;

0.2.wait ;

})

}).play(SystemClock)

)

removeVertex (vID)

Remove a vertex.

vID - the vertex identifier. Default value is nil.

(

g = Graph.new ;

64.do({|i| g.addVertex(500.rand+300, 500.rand+150, 0, (64+i).asAscii) ;

g.addEdge(i+1, i+1, 1.0.rand) ;

}) ;

p = Painter(g) ;

Routine.new({

64.do({ |i| g.removeVertex(i+1) ; 0.2.wait })

}).play(SystemClock)

)

setEdgeDuration (eID, dur)

Set the duration of an edge.

eID - the edge identifier. Default value is nil.

dur - new duration. Default value is nil.

(

g = Graph.new

.addVertex(600, 400, 0, "bip")

.addEdge(1, 1, 1) ;

p = Painter(g) ;

Routine.new({

50.do({|i| g.setEdgeDuration(1, i+1) ;

0.1.wait });

p.w.close

}).play(SystemClock)

)

removeEdge (eID)

Remove the edges having eID as identifier.

eID - the edge identifier. Default value is nil.

(

g = Graph.new

.addVertex(600, 400, 0, "root")

.addEdge(1,1, 1) ;

p = Painter(g) ;

Routine({

63.do({ arg i ;

l = (64+i).asAscii ;

g.addVertex(1000.rand, 700.rand, 0, l) ;

// nv has been increased

g.addEdge(1, g.nv-1, 1.0.rand) ;

0.2.wait ;

}) ;

63.do({ arg i ;

g.removeEdge(i+2) ;

0.2.wait ;

})

}).play(SystemClock)

)

removeEdges (start, end)

Remove all the edges from start to end.

start - the starting vertex vID. Default value is nil.

end - the ending vertex vID. Default value is nil.

(

g = Graph.new

.addVertex(100, 400, 0, "A")

.addVertex(1100, 400, 0, "B") ;

p = Painter(g) ;

10.do({ arg i ;

// nv has been increased

g.addEdge(1, 2, i) ;

g.addEdge(2, 1, i*0.1) ;

}) ;

)

// from 1 to 2

g.removeEdges(1, 2);

// from 2 to 1

g.removeEdges(2, 1);

isolateVertex (vID)

Remove all the edges from and to vertex

vID - the vertex identifier. Default value is nil.

(

n = 64.collect({ arg i ; (64+i).asAscii }) ;

g = Graph.new.createRandomCyclic(n) ;

p = Painter(g) ;

Routine({

g.graphDict.keys.asArray.do({ arg key ;

g.isolateVertex(key) ;

0.2.wait ;

}) ;

1.5.wait ; p.w.close ;

}).play(SystemClock)

)

changeVertexName (vID, newLab)

Change the label of a vertex.

vID - the vertex identifier. Default value is nil.

newLab - new label (string or symbol). Default value is nil.

(

// vocals and consonants

v = 97+[0, 4, 8, 14, 20] ;

c = 97+(1..25).removeAll(v) ;

g = Graph.new.addVertex(600, 400, 0, "mama") ;

p = Painter(g, vDim: [300,80], fontName: "Times New Roman", fontSize: 60 ) ;

Routine ({

100.do({

l = c.choose.asAscii.asString

++ v.choose.asAscii.asString

++ c.choose.asAscii.asString

++ v.choose.asAscii.asString ;

g.changeVertexName(1, l) ;

0.3.wait

}) ;

p.w.close ;

}).play(SystemClock)

)

createRandom (nameList, eNum, eMin, eMax)

Starting from a list of labels, create a random graph with a eNum numebr of edges.

Edges's duration is in the range eMin, eMax.

nameList - a list of labels. Default value is nil.

eNum - number of edges connecting the list of vertices. Default value is 10.

eMin - minimum duration of edges. Default value is 1.

eMax - maximum duration of edges. Default value is 1.

(

// all SC classes

c = Object.subclasses.collect({ |i| i.name}) ;

// random connected by 200 edges

g = Graph.new.createRandom(c, 200);

p = Painter(g)

)

createRandomCyclic (nameList, eNum, eMin, eMax, noLoop)

Like createRandom, but add as many edges as needed to ensure that the graph is cyclic.

Particularly useful as if you want to test a graph you don't want to worry about connections.

The path is infinite and the actant(s) keep(s) on walking.

nameList - a list of labels. Default value is nil.

eNum - number of edges connecting the list of vertices. Default value is 10.

eMin - minimum duration of edges. Default value is 1.

eMax - maximum duration of edges. Default value is 1.

(

// all SC classes

c = Object.subclasses.collect({ |i| i.name}) ;

// random connected by 10 edges (default) plus all needed edges

g = Graph.new.createRandomCyclic(c);

p = Painter(g)

)

round (step)

Round edges to step. Useful for metric sequencing.

step - the rounding step. Default value is 0.

(

n = ["drum", "snare", "hihat", "tom"] ;

g = Graph.new.createRandom(n, 10, 0, 1);

p = Painter(g, eDim:[200,20]) ;

// increasing rounding

Routine({

14.do({ arg i ;

j = 1/(10**(13-i)) ;

g.round(j) ; 0.4.wait ;

}) ;

1.5.wait ; p.w.close ;

}).play(SystemClock)

)

plot

A convenience method to plot a graph. Note that it is static.

(

n = 64.collect({ arg i ; (64+i).asAscii }) ;

g = Graph.new

.createRandomCyclic(n)

.plot ;

)

If you want to use a Routine to see the graph dynamically changing, instantiate

a Painter:

(

n = 30.collect({ arg i ; (64+i).asAscii }) ;

g = Graph.new.createRandomCyclic(n) ;

p = Painter(g, eLabels: false) ;

Routine({

100.do({ arg i ;

g.changeVertexPosition(

(i%30+1).asInteger, (1200-(i*12)).rand, (800-(i*8)).rand

) ;

0.1.wait

}) ;

2.wait ; p.w.close ;

}).play(SystemClock)

)

Examples

See before