[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Patch: Connection optimization



Hi there,
today I worked a bit with Dia. 0.88.1 had severe problems with finding
fonts (although they should are there). So I tried the CVS version.

Later on, I noticed what would be a great feature. Take the following
situation:

+------+          +-------+
|      *----------*       |  (two rectangles connected by a line)
+------+          +-------+

If I move the left one to the right, I get:

                  +------+          +-------+
                  *-------------------------*
                  +------+          +-------+

Which I find rather annoying.

Therefore, I hacked around a bit (getting the concept of
ConnectionPoints, Connections and Handles right isn't that easy) and
produced the patch attached. It is more a proof-of-concept than a final
patch. An UI addition to enable/disable this behaviour (or maybe add
this as a property to the connection) is neccessary.

The patch only modifies the Connection object (and a small part of
connectionpoint_ops.c) - I think it should be factored out to be used by
other connection types as well (e.g. bezier, zig-zag). As I'm not
familiar with the Dia architecture, I could not find a suitable place.

Comments welcome!

Bye, Tino.

-- 
             * LINUX - Where do you want to be tomorrow? *
                  http://www.tu-chemnitz.de/linux/tag/
Index: app/connectionpoint_ops.c
===================================================================
RCS file: /cvs/gnome/dia/app/connectionpoint_ops.c,v
retrieving revision 1.9
diff -u -r1.9 connectionpoint_ops.c
--- app/connectionpoint_ops.c	23 Mar 2001 14:29:48 -0000	1.9
+++ app/connectionpoint_ops.c	21 May 2002 20:29:22 -0000
@@ -107,7 +107,13 @@
 	  if (connected_obj->handles[j]->connected_to == cp)
 	    handle = connected_obj->handles[j];
 	}
-	assert(handle!=NULL);
+	if (handle == NULL)
+	{
+	    /* the connection point might have been altered by calling
+	       move_handle below */
+	    list = g_list_next(list);
+	    continue;
+	}
 	
 	object_add_updates(connected_obj, dia);
 	connected_obj->ops->move_handle(connected_obj, handle ,
Index: lib/connection.c
===================================================================
RCS file: /cvs/gnome/dia/lib/connection.c,v
retrieving revision 1.9
diff -u -r1.9 connection.c
--- lib/connection.c	26 May 2001 01:11:48 -0000	1.9
+++ lib/connection.c	21 May 2002 20:29:23 -0000
@@ -24,6 +24,95 @@
 #include "connection.h"
 #include "message.h"
 
+static coord
+square_distance_point_point (Point p1, Point p2)
+{
+  const coord dx = p2.x - p1.x;
+  const coord dy = p2.y - p1.y;
+  return dx*dx+dy*dy;
+}
+
+
+static void
+optimize_connection (Connection* conn)
+{
+  ConnectionPoint* first_connpoint = conn->endpoint_handles[0].connected_to; 
+  ConnectionPoint* second_connpoint = conn->endpoint_handles[1].connected_to; 
+  ConnectionPoint* new_first_connpoint = first_connpoint;
+  ConnectionPoint* new_second_connpoint = second_connpoint;
+
+  Object* first_object; 
+  Object* second_object; 
+
+  ConnectionPoint** first_connections;
+  ConnectionPoint** second_connections;
+
+  coord min_distance;
+
+  int first_connection_num;
+
+  /* for now we only handle full connections */
+  if (   (first_connpoint == 0L)
+      || (second_connpoint == 0L))
+    return;
+
+  min_distance = square_distance_point_point (
+        first_connpoint->pos, second_connpoint->pos);
+
+  first_object = first_connpoint->object;
+  second_object = second_connpoint->object;
+
+  first_connections = first_object->connections;
+  second_connections = second_object->connections;
+
+  /* Now figure out the connections with the smallest distance. 
+     This is O(n*m) - not optimal but we're only proofing a concept */
+  for (first_connection_num = 0; first_connection_num < first_object->num_connections; first_connection_num++)
+  {
+     int second_connection_num;
+
+     for (second_connection_num = 0; second_connection_num < second_object->num_connections; second_connection_num++)
+     {
+        const coord distance = square_distance_point_point (
+                first_connections[first_connection_num]->pos, 
+                second_connections[second_connection_num]->pos);
+
+        if (distance < min_distance)
+        {
+          min_distance = distance;
+          new_first_connpoint = first_connections[first_connection_num];
+          new_second_connpoint = second_connections[second_connection_num];
+        }
+
+     }
+
+  }
+
+  if (new_first_connpoint != first_connpoint)
+  {
+    conn->endpoint_handles[0].connected_to = new_first_connpoint;
+
+    first_connpoint->connected = g_list_remove (first_connpoint->connected, conn);
+
+    new_first_connpoint->connected = g_list_prepend (new_first_connpoint->connected, conn);
+
+    conn->endpoints[0] = new_first_connpoint->pos;
+  }
+
+  if (new_second_connpoint != second_connpoint)
+  {
+    conn->endpoint_handles[1].connected_to = new_second_connpoint;
+
+    second_connpoint->connected = g_list_remove (second_connpoint->connected, conn);
+
+    new_second_connpoint->connected = g_list_prepend (new_second_connpoint->connected, conn);
+
+    conn->endpoints[1] = new_second_connpoint->pos;
+  }
+
+}
+
+
 void
 connection_move_handle(Connection *conn, HandleId id,
 		       Point *to, HandleMoveReason reason)
@@ -39,11 +128,15 @@
     message_error("Internal error in connection_move_handle.\n");
     break;
   }
+
+  optimize_connection (conn);
 }
 
 void
 connection_update_handles(Connection *conn)
 {
+  assert(conn != NULL);
+
   conn->endpoint_handles[0].id = HANDLE_MOVE_STARTPOINT;
   conn->endpoint_handles[0].pos = conn->endpoints[0];
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] Mail converted by Mofo Magic and the Flying D

 
All trademarks and copyrights are the property of their respective owners.

Other Directory Sites: SeekWonder | Directory Owners Forum

GuideSMACK