Upload
tcab22
View
528
Download
3
Embed Size (px)
DESCRIPTION
Talk to Melbourne Patterns Group by Andy Bulka in March 2011, Melbourne Australia. How to implement a UML layout algorithm including overlap removal, in python. Integrated into Andy's open source python UML tool PyNSource.
Citation preview
TopicsSpring LayoutMapping layout to Real WorldOGLMVCOverlap RemovalUnit tests and unit test diagramsMemento Design PatternBlackboard Design Pattern
injecting sorting functionFuture...
Summary 1My UML tool is written in PythonExisting layout libraries for e.g. python
PyGraphviz has no windows port so I wrote my own
Layout is reasonably hard to implement – academic papers are very complex and deal in a lot of math
DIRTY SECRET OF ACADEMIA - Layout algorithms only deal with ‘points’ and don’t take into account real width and height
Summary 2Thus you must run an overlap removal
algorithm after the layout to remove shape overlaps for any real world use (unless dealing with network and particle visualisation where each node is the same size/shape)
Overlap removal algorithm needs to minimise shape movement in order to respect the layout results
What I developedI used a ‘spring layout’ adapted from java and
javascriptI developed my own overlap removal
algorithmDeveloped a GUI sandbox test app for
development
Unit TestingExtensive unit tests were created to keep on
top of the layout algorithm results. A word document containing annotated screenshots for each test helped me enormously.
Unit TestingLayout / persistence format was created for
creating layout scenarios
{'type':'node', 'id':'D25', 'x':6, 'y':7, 'width':159, 'height':106}{'type':'node', 'id':'D13', 'x':6, 'y':119, 'width':119, 'height':73}{'type':'node', 'id':'m1', 'x':170, 'y':9, 'width':139, 'height':92}
Unit Testing Brittleness AvoidedLoose tests using (e.g. I created ‘ensureYorder ()’ etc) were
created so that the tests were not too brittle. Slight variations in position are ignored.
def test3_5InsertedVerticallyTwoPushedDown(self): self._LoadScenario3() # move m1 to the left node = self.g.FindNodeById('m1') node.left, node.top = (6, 4) # assert m1 has been inserted vertically - two pushed down were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual(2, self.overlap_remover.GetStats()['total_overlaps_found'])
self.assertTrue(self._ensureYorder('m1', 'D25', 'D13')) self.assertTrue(self._ensureXorder('m1', 'D97', 'D98')) self.assertTrue(self._ensureXorder('D25', 'D97', 'D98'))
Design Patterns Used - MementoMemento was used to remember graph
layout positions and then compare mementos to see if anything had ‘changed’ and thus drop out of the Spring layout algorithm early
Memento was used to save/restore layouts in my test GUI – assigned to keys 0..9
Design Patterns Used - BlackboardBlackboard pattern used to run layout several times
and figure out which was the best, cleanest result using multiple criteria. Each run is a ‘snapshot’
Snapshot 1 [6] LL 0 NN pre rm overlaps 5 LN 0 scale 1.6 bounds 23 (500, 473) <---Snapshot 2 [4] LL 0 NN pre rm overlaps 5 LN 1 scale 1.4 bounds 30 (570, 537)Snapshot 3 [5] LL 0 NN pre rm overlaps 6 LN 2 scale 2.0 bounds 17 (444, 393)Snapshot 4 [2] LL 0 NN pre rm overlaps 4 LN 2 scale 1.4 bounds 34 (648, 537)Snapshot 5 [3] LL 0 NN pre rm overlaps 5 LN 4 scale 2.0 bounds 21 (427, 508)Snapshot 6 [1] LL 0 NN pre rm overlaps 10 LN 5 scale 2.0 bounds 18 (485, 379)
def sortfunc(d): # this does the thinking! return (d['LL'], d['LN'], d['bounds_area_simple'], -d['scale'], d['NN_pre_OR'])
Python goodness helped in this ‘AI’ smartness
Future“Line over node” overlap was abandoned as
it started to get really complex with a lot of trigonometry and perhaps this area needs a more academic approach
Non straight lines and line routing is probably the better direction
Adding an understanding of UML semantics is another direction to research, so that e.g. base classes are above derived classes etc.
Code and LinksCode is python, open sourcePart of my python UML tool PyNSource - link
Reverse engineer python source code into UML - display UML as Ascii art or in a proper diagramming visual workspace. You can also generate java and delphi skeleton code from the python, for the purpose of importing that into other UML tools.
Seehttp://www.andypatterns.com/index.php/products/pynsource/