That's as far as I've gotten until 2 months ago (no work has been done
since, have been busy with post-graduate courses). As far as I can
remember, I didn't go on because of the fact that too many
recalculations will have to happen without a data structure for
caching the graph.

On Mon, Oct 13, 2008 at 12:12 AM, Fred Morcos <[email protected]> wrote:
> I am wondering again how to run your plugin.
>
> dia.register_action ("LayoutForcePy", "Layout (force)",
> "/DisplayMenu/Test/TestExtensionStart", layout_force_cb)
>
> What's the DisplayMenu?
>
> On Sun, Oct 12, 2008 at 10:35 PM, Hans Breuer <[email protected]> wrote:
>> At 12.10.2008 19:07, Fred Morcos wrote:
>>>
>>> On Sun, Oct 12, 2008 at 6:55 PM, Hans Breuer <[email protected]> wrote:
>>>>
>>>> At 08.10.2008 16:50, Fred Morcos wrote:
>>>>>
>>>>> Sorry for the very late reply, I have been finalizing my thesis and
>>>>> moving back to my country. I would like to restart the discussion
>>>>> about automatic layout, gearing things towards inclusion into Dia as
>>>>> an offered feature.
>>>>>
>>>>> You would prefer it as a plugin (I presume)?
>>>>
>>>> Yes.
>>>>>
>>>>> If it is a plugin, where should the GUI code go (if any)?
>>>>
>>>> In the plug-in. I did the necessary changes to your code some time ago,
>>>> but
>>>> that may be lost in some email. I have now added the plug-in to bugzilla.
>>>> See: http://bugzilla.gnome.org/show_bug.cgi?id=556026
>>>>
>>>
>>> I forgot to mention that I am going to implement it in Python.
>>
>> Why would you want to do this? As mentioned before it definitely is no
>> requirement to get your code to be included with Dia.
>>
>>> That was why I asked about GUI code. So should I use pygtk?
>>>
>> If you would go with Python, yes.
>>
>>>>> Any requirements for the GUI (following a certain HIG)?
>>>>
>>>> You may want to read http://library.gnome.org/devel/hig-book/stable/. But
>>>> please keep in mind that Dia should rely only on GUI available with
>>>> vanilla
>>>> Gtk+ for portability easons.
>>>>>
>>>>> How can I generate the API docs for plugins? --with-hardbooks didn't
>>>>> work.
>>>>
>>>> There is no dedicated plug-in API documentation. Basically you can use
>>>> everything available from lib/* and nothing from app/*
>>>>
>>>
>>> Help > PyDia Docs is all what's there?
>>>
>> Almost, but see also: http://www.gnome.org/projects/dia/python.html
>>
>> -------- Hans "at" Breuer "dot" Org -----------
>> Tell me what you need, and I'll tell you how to
>> get along without it.                -- Dilbert
>> _______________________________________________
>> dia-list mailing list
>> [email protected]
>> http://mail.gnome.org/mailman/listinfo/dia-list
>> FAQ at http://live.gnome.org/Dia/Faq
>> Main page at http://live.gnome.org/Dia
>>
>>
>
>
>
> --
> Fred Morcos
> http://fredmorcos.blogspot.com/
> http://fredmorcos.googlecode.com/
>



-- 
Fred Morcos
http://fredmorcos.blogspot.com/
http://katoob.googlecode.com/
https://savannah.nongnu.org/projects/objective-gtk/
http://grafer.googlecode.com/
#	autolayoutforcefast.py - Fast Diagram Layout Plugin for Dia
#	
#	Diagram Automatic Layout Plugin for Dia.
#
#	Copyright (c) 2008 Frederic-Gerald Morcos <[email protected]>
#	Copyright (c) 2008 Hans Breuer <[email protected]>
#
#	This program is free software; you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation; either version 2 of the License, or
#	(at your option) any later version.
#
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#
#	You should have received a copy of the GNU General Public License
#	along with this program; if not, write to the Free Software
#	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import dia, gtk, math

class LayoutUI(gtk.Window):
	def __init__(self):
		gtk.Window.__init__(self)
		self.set_border_width(5)
		self.set_skip_pager_hint(True)
		self.set_skip_taskbar_hint(True)
		# FIXME - self.set_transient_for() on Dia's main window
		box = gtk.VBox(False, 5)
		connBox = gtk.HBox(False, 5)
		connLabel = gtk.Label('Connection Length:')
		self.connSpin = gtk.SpinButton(gtk.Adjustment(1, 1, 500, 1, 10))
		connBox.pack_start(connLabel, False, False, 2)
		connBox.pack_start(self.connSpin, True, True, 2)
		buttBox = gtk.HButtonBox()
		buttBox.set_spacing(5)
		buttBox.set_layout(gtk.BUTTONBOX_END)
		self.buttApply = gtk.Button(None, gtk.STOCK_APPLY)
		buttClose = gtk.Button(None, gtk.STOCK_CLOSE)
		buttClose.connect('clicked', self.buttClose_clicked, None)
		buttBox.pack_start(self.buttApply, False, False, 2)
		buttBox.pack_start(buttClose, False, False, 2)
		box.pack_start(connBox, False, False, 2)
		box.pack_start(gtk.HSeparator(), False, False, 2)
		box.pack_start(buttBox, False, False, 2)
		self.add(box)
		self.show_all()
	
	def buttClose_clicked(self, widget, data):
		self.destroy()

def fast_layout_force_cb (data, flags):
	nodes = []
	connections = []

	for i in data.selected:
		if isConnection(i):
			connections.append(i)
		else:
			nodes.append(i)

	win = LayoutUI()
	win.buttApply.connect(
			'clicked', buttApply_clicked, 
			nodes, connections, win.connSpin, data)

def fast_layout_force(nodes, connections, connLen, 
		rconst, aconst, timestep, damping):
	
	energy = [0.0, 0.0]
	
	i = 0
	netforces = []
	while i < len(nodes):
		netforces.append([0.0, 0.0])
		i += 1

	for i, n in enumerate(nodes):
		for j, nn in enumerate(nodes[i + 1 : len(nodes)]):
			res = repulsion (n, nn, rconst)
			netforces[i][0] += res[0]
			netforces[i][1] += res[1]
			netforces[j][0] -= res[0]
			netforces[j][1] -= res[1]
	
#	for c in connections:
#		attraction (c, connLen, aconst, energy)

	for i, n in enumerate(nodes):
		update(timestep, damping, n, netforces[i], energy)
	
	return energy

def repulsion(node1, node2, const):
	pos1 = node1.properties['obj_pos'].value
	pos2 = node2.properties['obj_pos'].value

	dx = pos1.x - pos2.x
	dy = pos1.y - pos2.y

	numer = area(node1) * area(node2) * const
	denom = math.pow(dx * dx + dy * dy, 1.5)

	try:
		resx = numer * dx / denom
		resy = numer * dy / denom
	except ZeroDivisionError:
		print 'Repulsion: Zero division error.'
		return 0, 0

	return resx, resy

def update(timestep, damping, object, netforce, energy):
	velocity = [0.0, 0.0]

	velocity[0] = timestep * netforce[0] * damping
	velocity[1] = timestep * netforce[1] * damping
	
	p = object.properties['obj_pos'].value
	px = p.x + timestep * velocity[0]
	py = p.y + timestep * velocity[1]
	object.move(px, py)

	mass = area(object)
	energy[0] += mass * math.pow(velocity[0], 2) / 2
	energy[1] += mass * math.pow(velocity[1], 2) / 2

def area(object):
	rect = object.bounding_box
	return (rect.bottom - rect.top) * (rect.right - rect.left)

def buttApply_clicked(widget, nodes, connections, connSpin, data):
	connLen = connSpin.get_value_as_int()
	diagram = dia.active_display().diagram

	loops = 0
	energy = fast_layout_force(
			nodes, connections, connLen, 2.0, 3.0, 2e-1, 5e-1)
	while (energy[0] > 1 or energy[1] > 1) and loops < 100:
		energy = fast_layout_force(
				nodes, connections, connLen, 2.0, 3.0, 2e-1, 5e-1)
		loops += 1

	for n in nodes:
		diagram.update_connections(n)

	data.active_layer.update_extents()
	diagram.update_extents()
	diagram.flush()

	print loops, 'iterations.'

def isConnection (o):
	for connPoint in o.connections:
		if len (connPoint.connected) > 0:
			return False
	return True
	
dia.register_action (
		'FastLayoutForcePy', 
		'Fast Layout (force)', 
		'/DisplayMenu/Test/TestExtensionStart',
		fast_layout_force_cb)

_______________________________________________
dia-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/dia-list
FAQ at http://live.gnome.org/Dia/Faq
Main page at http://live.gnome.org/Dia

Reply via email to