Here are two basic types of diagrams along with their typical implementations:
Tight graphics :
Sparse graphs :
In the framework (unfortunately, the source is closed), which I wrote (> 12k loc graph uses +> 5k loc unit tests and still counts) I was in the state (Directed / Undirected / Mixed) Hypergraphs (Directed / Undirected / Mixed) Multigraphs , (Directed / Undirected / Mixed) Ordered Charts, (Directed / Undirected / Mixed) KPartite Graphs , as well as all kinds of Trees, such as Generic Trees, (A, B) -Trees, KAry-Trees, Full-KAry-Trees , (Trees in front: VP-trees, KD-trees, BKTrees, B-trees, R-trees, octers , ...).
And all without a single vertex or edge class. Pure generics. And without any redundant implementations **
Oh, and as if that wasn't enough, they all exist as mutable, immutable, observable ( NSNotification ), thread-safe, and thread-safe versions.
How? Thanks to the excessive use of Decorators .
In principle, all graphs are mutable, unsafe, and not observable. Therefore, I use Decorators to add all kinds of tastes to them (the result is no more than 35 classes, and no more than 500+ if they are implemented without decorators).
While I canβt give any real code, my graphs are mainly implemented through Lists using mostly NSMutableDictionaries and NSMutableSets (and NSMutableArrays for my ordered trees).
My indirect sparse graph has nothing but these ivars, for example:
NSMutableDictionary *vertices; NSMutableDictionary *edges;
Ivar vertices maps vertices onto vertex adjacency maps on falling edges ( {"vertex": {"vertex": "edge"}} )
Ivar edges maps edges to falling pairs of vertices ( {"edge": {"vertex", "vertex"}} ), and Pair is a paired data object that has a vertex of an edge vertex and a tail vertex.
Mixed sparse plots would have a slightly different display of adjacency / incident lists as well as Directional sparse plots , but you should get this idea.
The limitation of this implementation is that each and every vertex and each edge must have an object associated with it. And to make things more interesting (sic!), Each vertex object must be unique, and each edge object. This means that dictionaries do not allow duplicate keys. In addition, objects must implement NSCopying . NSValueTransformers or encapsulation of values ββis a way around these restrictions (the same goes for memory overhead from copying dictionary keys).
While the implementation has its drawbacks, there is a big benefit: universal versatility! There is hardly any type graph that I could think of that it is impossible to archive what I already have. Instead of building each type of graph with custom parts, you basically go to your box of lego blocks and assemble the graphs as you need.
Additional Information:
Each large graph type has its own protocol, here are a few:
HypergraphProtocol MultigraphProtocol [tagging protocol] (allows parallel edges) GraphProtocol (allows directed & undirected edges) UndirectedGraphProtocol [tagging protocol] (allows only undirected edges) DirectedGraphProtocol [tagging protocol] (allows only directed edges) ForestProtocol (allows sets of disjunct trees) TreeProtocol (allows trees) ABTreeProtocol (allows trees of ab children per vertex) FullKAryTreeProtocol [tagging protocol] (allows trees of either 0 or k children per vertex)
Attachment to a protocol implies innate nature (of both protocols and implementations).
If there is anything else that you would like to get some understanding, feel free to leave a comment.
Ps . To give credit where credit should be: The architecture is heavily dependent on the JUNG Java Graphics Framework (55k + loc).
Pps Before choosing this type of implementation, I wrote a little brother using only undirected graphs, which I wanted to expand to also support oriented graphs. My implementation was very similar to the one you provide in your question. This is what gave my first (rather naive) project a sharp end, then: Subclassing a set of interdependent classes in Objective-C and ensuring type safety. Adding a simple focus to my graph makes my whole code split. (I didnβt even use the solution I posted then, as that would just put off the pain). Now with the general implementation, I have implemented more than 20 graph options without any hacks. It's worth it.
If all you need is to draw a graph and move its nodes on the screen, it will be good if you just implement a general class of the graph, which can then be expanded to a certain direction, if necessary.