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

gEDA-cvs: gaf.git: branch: master updated (1.5.0-20080706-407-g67daa4d)



The branch, master has been updated
       via  67daa4d705d62d16133feb2d9a3a77cacb9b34de (commit)
       via  94602fdc724dd31527c3ceed2092ddeee1d954e0 (commit)
      from  d785f7cf34f581bbb18fbc73dced8e44bc28ab90 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


=========
 Summary
=========

 gschem/src/o_find.c              |    4 +-
 libgeda/include/prototype_priv.h |   27 ++++++++---
 libgeda/src/Makefile.am          |    3 +
 libgeda/src/m_box.c              |   85 ++++++++++++++++++++++++++++++++++
 libgeda/src/m_circle.c           |   69 +++++++++++++++++++++++++++
 libgeda/src/m_line.c             |   95 ++++++++++++++++++++++++++++++++++++++
 libgeda/src/m_polygon.c          |    5 +--
 libgeda/src/o_arc_basic.c        |    9 ++--
 libgeda/src/o_basic.c            |   28 +++++++++--
 libgeda/src/o_box_basic.c        |   39 ++++------------
 libgeda/src/o_circle_basic.c     |   23 ++++------
 libgeda/src/o_complex_basic.c    |   46 ++++++++++++++++--
 libgeda/src/o_line_basic.c       |   50 ++-----------------
 libgeda/src/o_path_basic.c       |   33 +++----------
 libgeda/src/o_picture.c          |   10 ++--
 libgeda/src/o_text_basic.c       |    9 ++--
 libgeda/src/s_path.c             |   37 +++++++++++++++
 17 files changed, 422 insertions(+), 150 deletions(-)
 create mode 100644 libgeda/src/m_box.c
 create mode 100644 libgeda/src/m_circle.c
 create mode 100644 libgeda/src/m_line.c


=================
 Commit Messages
=================

commit 67daa4d705d62d16133feb2d9a3a77cacb9b34de
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sat Dec 20 05:49:39 2008 +0000

    Allow bounds of lines and arcs inside a COMPLEX to form a selectable box.
    
    This allows existing symbols, such as logic gates etc.. which have no
    outer box, nor yet make use of closed paths, to be easily selectable.

:100644 100644 60be4b7... d14a8b8... M	libgeda/src/o_complex_basic.c

commit 94602fdc724dd31527c3ceed2092ddeee1d954e0
Author: Edward Hennessy <ehennes@xxxxxxxxxxxxx>
Date:   Sat Dec 20 04:42:25 2008 +0000

    Symbols now selectable by clicking inside their shapes.
    
    This patch changes the selection behavior by allowing symbols to
    be selected by clicking inside any contained shape.  This behavior
    works for symbols with boxes, circles, and paths.
    
    Patch modified by Peter Clifton:
    
      Added m_line_shortest_distance(), (m_line.c) and make use of that
      in m_polygon_shortest_distance() rather than faking a line OBJECT.
    
      Change all o_*_shortest_distance() functions to take a parameter
      "force_solid" so we avoid having to use a specialised dispatch
      function to treat constituent primitive objects inside a COMPLEX
      as solid.

:100644 100644 6042d81... b0281ff... M	gschem/src/o_find.c
:100644 100644 7807cef... 813421a... M	libgeda/include/prototype_priv.h
:100644 100644 78e025b... 5b04947... M	libgeda/src/Makefile.am
:000000 100644 0000000... 6df9846... A	libgeda/src/m_box.c
:000000 100644 0000000... 815d54e... A	libgeda/src/m_circle.c
:000000 100644 0000000... 7c1b0e2... A	libgeda/src/m_line.c
:100644 100644 175e6fc... e921a82... M	libgeda/src/m_polygon.c
:100644 100644 0800e02... 812adec... M	libgeda/src/o_arc_basic.c
:100644 100644 c7c88c8... db3b38c... M	libgeda/src/o_basic.c
:100644 100644 48236a5... 236b3b3... M	libgeda/src/o_box_basic.c
:100644 100644 ceeaa92... 8372cd5... M	libgeda/src/o_circle_basic.c
:100644 100644 37f580e... 60be4b7... M	libgeda/src/o_complex_basic.c
:100644 100644 6abd97e... ac899f6... M	libgeda/src/o_line_basic.c
:100644 100644 172da4f... 22c7d43... M	libgeda/src/o_path_basic.c
:100644 100644 aa15b46... 312e5ef... M	libgeda/src/o_picture.c
:100644 100644 43c22ad... 55a1a48... M	libgeda/src/o_text_basic.c
:100644 100644 ab94fef... 3a52ba1... M	libgeda/src/s_path.c

=========
 Changes
=========

commit 67daa4d705d62d16133feb2d9a3a77cacb9b34de
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sat Dec 20 05:49:39 2008 +0000

    Allow bounds of lines and arcs inside a COMPLEX to form a selectable box.
    
    This allows existing symbols, such as logic gates etc.. which have no
    outer box, nor yet make use of closed paths, to be easily selectable.

diff --git a/libgeda/src/o_complex_basic.c b/libgeda/src/o_complex_basic.c
index 60be4b7..d14a8b8 100644
--- a/libgeda/src/o_complex_basic.c
+++ b/libgeda/src/o_complex_basic.c
@@ -1552,6 +1552,8 @@ double o_complex_shortest_distance (OBJECT *object, int x, int y,
 {
   double shortest_distance = G_MAXDOUBLE;
   double distance;
+  int found_line_bounds = 0;
+  BOX line_bounds;
   GList *iter;
 
   g_return_val_if_fail (object->complex != NULL, G_MAXDOUBLE);
@@ -1560,7 +1562,33 @@ double o_complex_shortest_distance (OBJECT *object, int x, int y,
        iter != NULL; iter= g_list_next (iter)) {
     OBJECT *obj = iter->data;
 
-    distance = o_shortest_distance_full (obj, x, y, TRUE);
+    /* Collect the bounds of any lines and arcs in the symbol */
+    if ((obj->type == OBJ_LINE || obj->type == OBJ_ARC) &&
+        obj->w_bounds_valid) {
+
+      if (found_line_bounds) {
+        line_bounds.lower_x = min (line_bounds.lower_x, obj->w_left);
+        line_bounds.lower_y = min (line_bounds.lower_y, obj->w_top);
+        line_bounds.upper_x = max (line_bounds.upper_x, obj->w_right);
+        line_bounds.upper_y = max (line_bounds.upper_y, obj->w_bottom);
+      } else {
+        line_bounds.lower_x = obj->w_left;
+        line_bounds.lower_y = obj->w_top;
+        line_bounds.upper_x = obj->w_right;
+        line_bounds.upper_y = obj->w_bottom;
+        found_line_bounds = 1;
+      }
+    } else {
+      distance = o_shortest_distance_full (obj, x, y, TRUE);
+      shortest_distance = min (shortest_distance, distance);
+    }
+
+    if (shortest_distance == 0.0)
+      return shortest_distance;
+  }
+
+  if (found_line_bounds) {
+    distance = m_box_shortest_distance (&line_bounds, x, y, TRUE);
     shortest_distance = min (shortest_distance, distance);
   }
 

commit 94602fdc724dd31527c3ceed2092ddeee1d954e0
Author: Edward Hennessy <ehennes@xxxxxxxxxxxxx>
Date:   Sat Dec 20 04:42:25 2008 +0000

    Symbols now selectable by clicking inside their shapes.
    
    This patch changes the selection behavior by allowing symbols to
    be selected by clicking inside any contained shape.  This behavior
    works for symbols with boxes, circles, and paths.
    
    Patch modified by Peter Clifton:
    
      Added m_line_shortest_distance(), (m_line.c) and make use of that
      in m_polygon_shortest_distance() rather than faking a line OBJECT.
    
      Change all o_*_shortest_distance() functions to take a parameter
      "force_solid" so we avoid having to use a specialised dispatch
      function to treat constituent primitive objects inside a COMPLEX
      as solid.

diff --git a/gschem/src/o_find.c b/gschem/src/o_find.c
index 6042d81..b0281ff 100644
--- a/gschem/src/o_find.c
+++ b/gschem/src/o_find.c
@@ -61,7 +61,7 @@ gboolean o_find_object(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y,
     if (inside_region(o_current->w_left - w_slack, o_current->w_top - w_slack,
                       o_current->w_right + w_slack, o_current->w_bottom + w_slack,
                       w_x, w_y) &&
-        o_shortest_distance( o_current, w_x, w_y ) < w_slack ) {
+        o_shortest_distance (o_current, w_x, w_y) < w_slack ) {
       if (o_current->sel_func != NULL &&
           (o_current->visibility == VISIBLE || toplevel->show_hidden_text)) {
         if (change_selection) {
@@ -95,7 +95,7 @@ gboolean o_find_object(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y,
     if (inside_region(o_current->w_left - w_slack, o_current->w_top - w_slack,
                       o_current->w_right + w_slack, o_current->w_bottom + w_slack,
                       w_x, w_y) &&
-        o_shortest_distance( o_current, w_x, w_y ) < w_slack ) {
+        o_shortest_distance (o_current, w_x, w_y) < w_slack) {
 
       if (o_current->sel_func != NULL &&
           (o_current->visibility == VISIBLE || toplevel->show_hidden_text)) {
diff --git a/libgeda/include/prototype_priv.h b/libgeda/include/prototype_priv.h
index 7807cef..813421a 100644
--- a/libgeda/include/prototype_priv.h
+++ b/libgeda/include/prototype_priv.h
@@ -55,9 +55,18 @@ SCM g_get_page_filename(SCM page_smob);
 void m_bounds_init(BOUNDS *bounds);
 void m_bounds_of_points(BOUNDS *bounds, sPOINT points[], gint count);
 
+/* m_box.c */
+double m_box_shortest_distance (BOX *box, int x, int y, int solid);
+
+/* m_circle.c */
+double m_circle_shortest_distance (CIRCLE *circle, int x, int y, int solid);
+
 /* m_hatch.c */
 void m_hatch_polygon(GArray *points, gint angle, gint pitch, GArray *lines);
 
+/* m_line.c */
+double m_line_shortest_distance (LINE *circle, int x, int y);
+
 /* m_polygon.c */
 gboolean m_polygon_interior_point(GArray *points, int x, int y);
 double m_polygon_shortest_distance(GArray *points, int x, int y, gboolean closed);
@@ -83,7 +92,7 @@ void o_arc_print_dotted(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius,
 void o_arc_print_dashed(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius, int angle1, int angle2, int color, int arc_width, int length, int space, int origin_x, int origin_y);
 void o_arc_print_center(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius, int angle1, int angle2, int color, int arc_width, int length, int space, int origin_x, int origin_y);
 void o_arc_print_phantom(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius, int angle1, int angle2, int color, int arc_width, int length, int space, int origin_x, int origin_y);
-double o_arc_shortest_distance(OBJECT *object, int x, int y);
+double o_arc_shortest_distance(OBJECT *object, int x, int y, int force_soild);
 gboolean o_arc_within_sweep(ARC *arc, gint x, gint y);
 void world_get_arc_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom);
 void o_arc_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
@@ -98,6 +107,7 @@ GList *o_read_attribs(TOPLEVEL *toplevel,
 
 /* o_basic.c */
 void o_bounds_invalidate(TOPLEVEL *toplevel, OBJECT *object);
+double o_shortest_distance_full(OBJECT *object, int x, int y, int force_solid);
 
 /* o_box_basic.c */
 OBJECT *o_box_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver);
@@ -111,7 +121,7 @@ void o_box_print_phantom(TOPLEVEL *toplevel, FILE *fp, int x, int y, int width,
 void o_box_print_filled(TOPLEVEL *toplevel, FILE *fp, int x, int y, int width, int height, int color, int fill_width, int angle1, int pitch1, int angle2, int pitch2, int origin_x, int origin_y);
 void o_box_print_mesh(TOPLEVEL *toplevel, FILE *fp, int x, int y, int width, int height, int color, int fill_width, int angle1, int pitch1, int angle2, int pitch2, int origin_x, int origin_y);
 void o_box_print_hatch(TOPLEVEL *toplevel, FILE *fp, int x, int y, int width, int height, int color, int fill_width, int angle1, int pitch1, int angle2, int pitch2, int origin_x, int origin_y);
-double o_box_shortest_distance(OBJECT *object, int x, int y);
+double o_box_shortest_distance(OBJECT *object, int x, int y, int force_soild);
 void world_get_box_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom);
 void o_box_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
 
@@ -134,14 +144,14 @@ void o_circle_print_phantom(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radi
 void o_circle_print_filled(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius, int color, int fill_width, int angle1, int pitch1, int angle2, int pitch2, int origin_x, int origin_y);
 void o_circle_print_mesh(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius, int color, int fill_width, int angle1, int pitch1, int angle2, int pitch2, int origin_x, int origin_y);
 void o_circle_print_hatch(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius, int color, int fill_width, int angle1, int pitch1, int angle2, int pitch2, int origin_x, int origin_y);
-double o_circle_shortest_distance(OBJECT *object, int x, int y);
+double o_circle_shortest_distance(OBJECT *object, int x, int y, int force_soild);
 void world_get_circle_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom);
 void o_circle_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
 
 /* o_complex_basic.c */
 OBJECT *o_complex_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver);
 char *o_complex_save(OBJECT *object);
-double o_complex_shortest_distance(OBJECT *object, int x, int y);
+double o_complex_shortest_distance(OBJECT *object, int x, int y, int force_soild);
 void world_get_complex_bounds(TOPLEVEL *toplevel, OBJECT *complex, int *left, int *top, int *right, int *bottom);
 void o_complex_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
 
@@ -154,7 +164,7 @@ void o_line_print_dotted(TOPLEVEL *toplevel, FILE *fp, int x1, int y1, int x2, i
 void o_line_print_dashed(TOPLEVEL *toplevel, FILE *fp, int x1, int y1, int x2, int y2, int color, int line_width, int length, int space, int origin_x, int origin_y);
 void o_line_print_center(TOPLEVEL *toplevel, FILE *fp, int x1, int y1, int x2, int y2, int color, int line_width, int length, int space, int origin_x, int origin_y);
 void o_line_print_phantom(TOPLEVEL *toplevel, FILE *fp, int x1, int y1, int x2, int y2, int color, int line_width, int length, int space, int origin_x, int origin_y);
-double o_line_shortest_distance(OBJECT *object, int x, int y);
+double o_line_shortest_distance(OBJECT *object, int x, int y, int force_soild);
 void world_get_line_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom);
 void o_line_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
 
@@ -169,7 +179,7 @@ void o_net_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
 OBJECT *o_path_read(TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb, unsigned int release_ver, unsigned int fileformat_ver);
 char *o_path_save(OBJECT *object);
 void o_path_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y);
-double o_path_shortest_distance(OBJECT *object, int x, int y);
+double o_path_shortest_distance(OBJECT *object, int x, int y, int force_soild);
 void world_get_path_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom);
 void o_path_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
 
@@ -179,7 +189,7 @@ OBJECT *o_picture_read(TOPLEVEL *toplevel, const char *first_line, TextBuffer *t
 char *o_picture_save(OBJECT *object);
 void o_picture_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
 		     int origin_x, int origin_y);
-double o_picture_shortest_distance(OBJECT *object, int x, int y);
+double o_picture_shortest_distance(OBJECT *object, int x, int y, int force_soild);
 void world_get_picture_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom);
 void o_picture_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
 
@@ -195,7 +205,7 @@ OBJECT *o_text_read(TOPLEVEL *toplevel, const char *first_line, TextBuffer *tb,
 char *o_text_save(OBJECT *object);
 void o_text_print_text_string(FILE *fp, char *string, int unicode_count, gunichar *unicode_table);
 void o_text_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y, int unicode_count, gunichar *unicode_table);
-double o_text_shortest_distance(OBJECT *object, int x, int y);
+double o_text_shortest_distance(OBJECT *object, int x, int y, int force_soild);
 int world_get_text_bounds(TOPLEVEL *toplevel, OBJECT *o_current, int *left, int *top, int *right, int *bottom);
 void o_text_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
 
@@ -212,6 +222,7 @@ gchar* s_encoding_base64_decode (gchar* src, guint srclen, guint* dstlenp);
 
 /* s_path.c */
 void s_path_to_polygon(PATH *path, GArray *points);
+double s_path_shortest_distance (PATH *path, int x, int y, int solid);
 
 /* s_textbuffer.c */
 TextBuffer *s_textbuffer_new (gchar *data, const gint size);
diff --git a/libgeda/src/Makefile.am b/libgeda/src/Makefile.am
index 78e025b..5b04947 100644
--- a/libgeda/src/Makefile.am
+++ b/libgeda/src/Makefile.am
@@ -26,7 +26,10 @@ libgeda_la_SOURCES = \
 	libgeda.c \
 	m_basic.c \
 	m_bounds.c \
+	m_box.c \
+	m_circle.c \
 	m_hatch.c \
+	m_line.c \
 	m_polygon.c \
 	m_transform.c \
 	o_arc_basic.c \
diff --git a/libgeda/src/m_box.c b/libgeda/src/m_box.c
new file mode 100644
index 0000000..6df9846
--- /dev/null
+++ b/libgeda/src/m_box.c
@@ -0,0 +1,85 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2008 Ales Hvezda
+ * Copyright (C) 1998-2008 gEDA Contributors (see ChangeLog for details)
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+
+/*! \file m_box.c
+ *
+ *  \brief Low-level mathmatical functions for boxes
+ */
+
+#include <config.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "libgeda_priv.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+
+/*! \brief Calculates the distance between the given point and the closest
+ *  point on the perimeter or interior of the box.
+ *
+ *  \param [in] box    The box.
+ *  \param [in] x      The x coordinate of the given point.
+ *  \param [in] y      The y coordinate of the given point.
+ *  \param [in] solid  TRUE if the box should be treated as solid, FALSE if
+ *  the box should be treated as hollow.
+ *  \return The shortest distance from the box to the point.  With a solid
+ *  shape, this function returns a distance of zero for interior points.  With
+ *  an invalid parameter, this function returns G_MAXDOUBLE.
+ */
+double m_box_shortest_distance (BOX *box, int x, int y, int solid)
+{
+  double shortest_distance;
+  double x1, y1, x2, y2;
+  double dx, dy;
+
+  g_return_val_if_fail (box != NULL, G_MAXDOUBLE);
+
+  x1 = (double) min (box->upper_x, box->lower_x);
+  y1 = (double) min (box->upper_y, box->lower_y);
+  x2 = (double) max (box->upper_x, box->lower_x);
+  y2 = (double) max (box->upper_y, box->lower_y);
+
+  dx = min (((double)x) - x1, x2 - ((double)x));
+  dy = min (((double)y) - y1, y2 - ((double)y));
+
+  if (solid) {
+    dx = min (dx, 0);
+    dy = min (dy, 0);
+  }
+
+  if (dx < 0) {
+    if (dy < 0) {
+      shortest_distance = sqrt ((dx * dx) + (dy * dy));
+    } else {
+      shortest_distance = fabs (dx);
+    }
+  } else {
+    if (dy < 0) {
+      shortest_distance = fabs (dy);
+    } else {
+      shortest_distance = min (dx, dy);
+    }
+  }
+
+  return shortest_distance;
+}
diff --git a/libgeda/src/m_circle.c b/libgeda/src/m_circle.c
new file mode 100644
index 0000000..815d54e
--- /dev/null
+++ b/libgeda/src/m_circle.c
@@ -0,0 +1,69 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2008 Ales Hvezda
+ * Copyright (C) 1998-2008 gEDA Contributors (see ChangeLog for details)
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+
+/*! \file m_geometry.c
+ *
+ *  \brief Low-level mathmatical functions for circles
+ */
+
+#include <config.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "libgeda_priv.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+
+/*! \brief Calculates the distance between the given point and the closest
+ * point on the perimeter or interior of the circle.
+ *
+ *  \param [in] circle  The circle.
+ *  \param [in] x       The x coordinate of the given point.
+ *  \param [in] y       The y coordinate of the given point.
+ *  \param [in] solid   TRUE if the circle should be treated as solid, FALSE if
+ *  the circle should be treated as hollow.
+ *  \return The shortest distance from the circle to the point.  With a solid
+ *  shape, this function returns a distance of zero for interior points.  With
+ *  an invalid parameter, this function returns G_MAXDOUBLE.
+ */
+double m_circle_shortest_distance (CIRCLE *circle, int x, int y, int solid)
+{
+  double shortest_distance;
+  double distance_to_center;
+  double dx, dy;
+
+  g_return_val_if_fail (circle != NULL, G_MAXDOUBLE);
+
+  dx = ((double)x) - ((double)circle->center_x);
+  dy = ((double)y) - ((double)circle->center_y);
+
+  distance_to_center = sqrt ((dx * dx) + (dy * dy));
+
+  if (solid) {
+    shortest_distance = max (distance_to_center - circle->radius, 0);
+  } else {
+    shortest_distance = fabs (distance_to_center - circle->radius);
+  }
+
+  return shortest_distance;
+}
diff --git a/libgeda/src/m_line.c b/libgeda/src/m_line.c
new file mode 100644
index 0000000..7c1b0e2
--- /dev/null
+++ b/libgeda/src/m_line.c
@@ -0,0 +1,95 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2008 Ales Hvezda
+ * Copyright (C) 1998-2008 gEDA Contributors (see ChangeLog for details)
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+
+/*! \file m_geometry.c
+ *
+ *  \brief Low-level mathmatical functions for lines
+ */
+
+#include <config.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "libgeda_priv.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+
+/*! \brief Calculates the distance between the given point and the closest
+ *  point on the given line segment.
+ *
+ *  If the closest point on the line resides beyond the line segment's
+ *  end point, this function returns the distance from the given point to the
+ *  closest end point.
+ *
+ *  If the line represents a single point (the endpoints are the same), this
+ *  function calcualtes the distance to that point.
+ *
+ *  \param [in] line  The LINE object.
+ *  \param [in] x     The x coordinate of the given point.
+ *  \param [in] y     The y coordinate of the given point.
+ *  \return The shortest distance from the object to the point. With an
+ *  invalid parameter, this function returns G_MAXDOUBLE.
+ */
+double m_line_shortest_distance (LINE *line, int x, int y)
+{
+  double cx, cy;
+  double dx, dy;
+  double dx0, dy0;
+  double lx0, ly0;
+  double ldx, ldy;
+  double t;
+
+  g_return_val_if_fail (line != NULL, G_MAXDOUBLE);
+
+  lx0 = (double)line->x[0];
+  ly0 = (double)line->y[0];
+  ldx = (double)(line->x[1] - line->x[0]);
+  ldy = (double)(line->y[1] - line->y[0]);
+
+  if (ldx == 0 && ldy == 0) {
+    /* if line is a point, just calculate distance to the point */
+    dx = x - lx0;
+    dy = y - ly0;
+
+  } else {
+    /* calculate parametric value of perpendicular intersection */
+    dx0 = ldx * (x - lx0);
+    dy0 = ldy * (y - ly0);
+
+    t = (dx0 + dy0) / (ldx * ldx + ldy * ldy);
+
+    /* constrain the parametric value to a point on the line */
+    t = max (t, 0);
+    t = min (t, 1);
+
+    /* calculate closest point on the line */
+    cx = t * ldx + lx0;
+    cy = t * ldy + ly0;
+
+    /* calculate distance to closest point */
+    dx = x - cx;
+    dy = y - cy;
+  }
+
+  return sqrt ((dx * dx) + (dy * dy));
+}
diff --git a/libgeda/src/m_polygon.c b/libgeda/src/m_polygon.c
index 175e6fc..e921a82 100644
--- a/libgeda/src/m_polygon.c
+++ b/libgeda/src/m_polygon.c
@@ -168,11 +168,8 @@ double m_polygon_shortest_distance (GArray *points, int x, int y, gboolean close
 
     while (i < points->len) {
       double distance;
-      OBJECT object;
       LINE line;
 
-      object.line = &line;
-
       line.x[0] = point.x;
       line.y[0] = point.y;
 
@@ -181,7 +178,7 @@ double m_polygon_shortest_distance (GArray *points, int x, int y, gboolean close
       line.x[1] = point.x;
       line.y[1] = point.y;
 
-      distance = o_line_shortest_distance (&object, x, y);
+      distance = m_line_shortest_distance (&line, x, y);
 
       shortest = min (shortest, distance);
     }
diff --git a/libgeda/src/o_arc_basic.c b/libgeda/src/o_arc_basic.c
index 0800e02..812adec 100644
--- a/libgeda/src/o_arc_basic.c
+++ b/libgeda/src/o_arc_basic.c
@@ -1234,13 +1234,14 @@ void o_arc_print_phantom(TOPLEVEL *toplevel, FILE *fp,
 /*! \brief Calculates the distance between the given point and the closest
  * point on the perimeter of the arc.
  *
- *  \param [in] object  The arc OBJECT.
- *  \param [in] x       The x coordinate of the given point.
- *  \param [in] y       The y coordinate of the given point.
+ *  \param [in] object       The arc OBJECT.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
+ *  \param [in] force_solid  If true, force treating the object as solid.
  *  \return The shortest distance from the object to the point. With an
  *  invalid parameter, this function returns G_MAXDOUBLE.
  */
-double o_arc_shortest_distance (OBJECT *object, int x, int y)
+double o_arc_shortest_distance (OBJECT *object, int x, int y, int force_solid)
 {
   double shortest_distance;
   double radius;
diff --git a/libgeda/src/o_basic.c b/libgeda/src/o_basic.c
index c7c88c8..db3b38c 100644
--- a/libgeda/src/o_basic.c
+++ b/libgeda/src/o_basic.c
@@ -373,12 +373,13 @@ void o_mirror_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, O
   }
 }
 
+
 /*! \brief Calculates the distance between the given point and the closest
  * point on the given object.
  *
- *  \param [in] object The given object.
- *  \param [in] x      The x coordinate of the given point.
- *  \param [in] y      The y coordinate of the given point.
+ *  \param [in] object       The given object.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
  *  \return The shortest distance from the object to the point. If the
  *  distance cannot be calculated, this function returns a really large
  *  number (G_MAXDOUBLE).  If an error occurs, this function returns
@@ -386,8 +387,25 @@ void o_mirror_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, O
  */
 double o_shortest_distance (OBJECT *object, int x, int y)
 {
+  return o_shortest_distance_full (object, x, y, FALSE);
+}
+
+/*! \brief Calculates the distance between the given point and the closest
+ * point on the given object. Allows forcing objects to solid.
+ *
+ *  \param [in] object       The given object.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
+ *  \param [in] force_solid  If true, force treating the object as solid.
+ *  \return The shortest distance from the object to the point. If the
+ *  distance cannot be calculated, this function returns a really large
+ *  number (G_MAXDOUBLE).  If an error occurs, this function returns
+ *  G_MAXDOUBLE.
+ */
+double o_shortest_distance_full (OBJECT *object, int x, int y, int force_solid)
+{
   double shortest_distance = G_MAXDOUBLE;
-  double (*func) (OBJECT *, int, int) = NULL;
+  double (*func) (OBJECT *, int, int, int) = NULL;
 
   g_return_val_if_fail (object != NULL, G_MAXDOUBLE);
 
@@ -410,7 +428,7 @@ double o_shortest_distance (OBJECT *object, int x, int y)
   }
 
   if (func != NULL) {
-    shortest_distance = (*func) (object, x, y);
+    shortest_distance = (*func) (object, x, y, force_solid);
   }
 
   return shortest_distance;
diff --git a/libgeda/src/o_box_basic.c b/libgeda/src/o_box_basic.c
index 48236a5..236b3b3 100644
--- a/libgeda/src/o_box_basic.c
+++ b/libgeda/src/o_box_basic.c
@@ -1295,42 +1295,21 @@ void o_box_print_hatch(TOPLEVEL *toplevel, FILE *fp,
 /*! \brief Calculates the distance between the given point and the closest
  * point on the perimeter of the box.
  *
- *  \param [in] object  The box OBJECT.
- *  \param [in] x       The x coordinate of the given point.
- *  \param [in] y       The y coordinate of the given point.
- *  \return The shortest distance from the object to the point. With an 
+ *  \param [in] object       The box OBJECT.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
+ *  \param [in] force_solid  If true, force treating the object as solid.
+ *  \return The shortest distance from the object to the point. With an
  *  invalid parameter, this function returns G_MAXDOUBLE.
  */
-double o_box_shortest_distance (OBJECT *object, int x, int y)
+double o_box_shortest_distance (OBJECT *object, int x, int y, int force_solid)
 {
-  double shortest_distance;
-  double x1, y1, x2, y2;
-  double dx, dy;
+  int solid;
 
   g_return_val_if_fail (object->box != NULL, G_MAXDOUBLE);
 
-  x1 = (double) min (object->box->upper_x, object->box->lower_x);
-  y1 = (double) min (object->box->upper_y, object->box->lower_y);
-  x2 = (double) max (object->box->upper_x, object->box->lower_x);
-  y2 = (double) max (object->box->upper_y, object->box->lower_y);
+  solid = force_solid || object->fill_type != FILLING_HOLLOW;
 
-  dx = min (((double)x) - x1, x2 - ((double)x));
-  dy = min (((double)y) - y1, y2 - ((double)y));
-
-  if (dx < 0) {
-    if (dy < 0) {
-      shortest_distance = sqrt ((dx * dx) + (dy * dy));
-    } else {
-      shortest_distance = fabs (dx);
-    }
-  } else {
-    if (dy < 0) {
-      shortest_distance = fabs (dy);
-    } else {
-      shortest_distance = min (dx, dy);
-    }
-  }
-
-  return shortest_distance;
+  return m_box_shortest_distance (object->box, x, y, solid);
 }
 
diff --git a/libgeda/src/o_circle_basic.c b/libgeda/src/o_circle_basic.c
index ceeaa92..8372cd5 100644
--- a/libgeda/src/o_circle_basic.c
+++ b/libgeda/src/o_circle_basic.c
@@ -1105,27 +1105,22 @@ void o_circle_print_hatch(TOPLEVEL *toplevel, FILE *fp,
 /*! \brief Calculates the distance between the given point and the closest
  * point on the perimeter of the circle.
  *
- *  \param [in] object  The circle OBJECT.
- *  \param [in] x       The x coordinate of the given point.
- *  \param [in] y       The y coordinate of the given point.
+ *  \param [in] object       The circle OBJECT.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
+ *  \param [in] force_solid  If true, force treating the object as solid.
  *  \return The shortest distance from the object to the point.  With an
  *  invalid parameter, this function returns G_MAXDOUBLE.
  */
-double o_circle_shortest_distance (OBJECT *object, int x, int y)
+double o_circle_shortest_distance (OBJECT *object, int x, int y,
+                                   int force_solid)
 {
-  double shortest_distance;
-  double distance_to_center;
-  double dx, dy;
+  int solid;
 
   g_return_val_if_fail (object->circle != NULL, G_MAXDOUBLE);
 
-  dx = ((double)x) - ((double)object->circle->center_x);
-  dy = ((double)y) - ((double)object->circle->center_y);
+  solid = force_solid || object->fill_type != FILLING_HOLLOW;
 
-  distance_to_center = sqrt ((dx * dx) + (dy * dy));
-
-  shortest_distance = fabs (distance_to_center - object->circle->radius);
-
-  return shortest_distance;
+  return m_circle_shortest_distance (object->circle, x, y, solid);
 }
 
diff --git a/libgeda/src/o_complex_basic.c b/libgeda/src/o_complex_basic.c
index 37f580e..60be4b7 100644
--- a/libgeda/src/o_complex_basic.c
+++ b/libgeda/src/o_complex_basic.c
@@ -44,6 +44,7 @@
 /*! Default setting for complex draw function. */
 void (*complex_draw_func)() = NULL;
 
+
 /*! \brief Return the bounds of the given object.
  *  \par Given an object, calculate the bounds coordinates.
  *  \param [in] toplevel The toplevel structure.
@@ -1533,15 +1534,21 @@ done:
 /*! \brief Calculates the distance between the given point and the closest
  * point on an object within the complex object.
  *
- *  \param [in] object  The complex  OBJECT.
- *  \param [in] x       The x coordinate of the given point.
- *  \param [in] y       The y coordinate of the given point.
+ *  \note When querying the distance to our child objects, we always
+ *        force treating them as solid filled.
+ *        We ignore the force_solid argument to this function.
+ *
+ *  \param [in] object       The complex  OBJECT.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
+ *  \param [in] force_solid  If true, force treating the object as solid.
  *  \return The shortest distance from the object to the point. If the
  *  distance cannot be calculated, this function returns a really large
  *  number (G_MAXDOUBLE).  With an invalid parameter, this function returns
  *  G_MAXDOUBLE.
  */
-double o_complex_shortest_distance (OBJECT *object, int x, int y)
+double o_complex_shortest_distance (OBJECT *object, int x, int y,
+                                    int force_solid)
 {
   double shortest_distance = G_MAXDOUBLE;
   double distance;
@@ -1553,10 +1560,9 @@ double o_complex_shortest_distance (OBJECT *object, int x, int y)
        iter != NULL; iter= g_list_next (iter)) {
     OBJECT *obj = iter->data;
 
-    distance = o_shortest_distance (obj, x, y);
+    distance = o_shortest_distance_full (obj, x, y, TRUE);
     shortest_distance = min (shortest_distance, distance);
   }
 
   return shortest_distance;
 }
-
diff --git a/libgeda/src/o_line_basic.c b/libgeda/src/o_line_basic.c
index 6abd97e..ac899f6 100644
--- a/libgeda/src/o_line_basic.c
+++ b/libgeda/src/o_line_basic.c
@@ -1213,53 +1213,15 @@ double o_line_length(OBJECT *object)
  *  If the line represents a single point (the endpoints are the same), this
  *  function calcualtes the distance to that point.
  *
- *  \param [in] object  The line OBJECT.
- *  \param [in] x       The x coordinate of the given point.
- *  \param [in] y       The y coordinate of the given point.
+ *  \param [in] object       The line OBJECT.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
+ *  \param [in] force_solid  If true, force treating the object as solid.
  *  \return The shortest distance from the object to the point. With an
  *  invalid parameter, this function returns G_MAXDOUBLE.
  */
-double o_line_shortest_distance (OBJECT *object, int x, int y)
+double o_line_shortest_distance (OBJECT *object, int x, int y, int force_solid)
 {
-  double cx, cy;
-  double dx, dy;
-  double dx0, dy0;
-  double lx0, ly0;
-  double ldx, ldy;
-  double t;
-
-  g_return_val_if_fail (object->line != NULL, G_MAXDOUBLE);
-
-  lx0 = (double)object->line->x[0];
-  ly0 = (double)object->line->y[0];
-  ldx = (double)(object->line->x[1] - object->line->x[0]);
-  ldy = (double)(object->line->y[1] - object->line->y[0]);
-
-  if (ldx == 0 && ldy == 0) {
-    /* if line is a point, just calculate distance to the point */
-    dx = x - lx0;
-    dy = y - ly0;
-
-  } else {
-    /* calculate parametric value of perpendicular intersection */
-    dx0 = ldx * (x - lx0);
-    dy0 = ldy * (y - ly0);
-
-    t = (dx0 + dy0) / (ldx * ldx + ldy * ldy);
-
-    /* constrain the parametric value to a point on the line */
-    t = max (t, 0);
-    t = min (t, 1);
-
-    /* calculate closest point on the line */
-    cx = t * ldx + lx0;
-    cy = t * ldy + ly0;
-
-    /* calculate distance to closest point */
-    dx = x - cx;
-    dy = y - cy;
-  }
-
-  return sqrt ((dx * dx) + (dy * dy));
+  return m_line_shortest_distance (object->line, x, y);
 }
 
diff --git a/libgeda/src/o_path_basic.c b/libgeda/src/o_path_basic.c
index 172da4f..22c7d43 100644
--- a/libgeda/src/o_path_basic.c
+++ b/libgeda/src/o_path_basic.c
@@ -1038,36 +1038,19 @@ void o_path_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
 /*! \brief Calculates the distance between the given point and the closest
  *  point on the given path segment.
  *
- *  \param [in] object  The path OBJECT.
- *  \param [in] x       The x coordinate of the given point.
- *  \param [in] y       The y coordinate of the given point.
+ *  \param [in] object       The path OBJECT.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
+ *  \param [in] force_solid  If true, force treating the object as solid.
  *  \return The shortest distance from the object to the point.  With an
  *  invalid parameter, this function returns G_MAXDOUBLE.
  */
-double o_path_shortest_distance (OBJECT *object, int x, int y)
+double o_path_shortest_distance (OBJECT *object, int x, int y, int force_solid)
 {
-  double shortest_distance = G_MAXDOUBLE;
-  GArray *points;
-  gboolean solid;
+  int solid;
 
-  points = g_array_new (FALSE, FALSE, sizeof (sPOINT));
+  solid = force_solid || object->fill_type != FILLING_HOLLOW;
 
-  s_path_to_polygon (object->path, points);
-
-  solid = object->fill_type != FILLING_HOLLOW;    /* FIXME */
-
-  if (!solid) {
-    shortest_distance = m_polygon_shortest_distance (points, x, y, FALSE);
-
-  } else if (m_polygon_interior_point (points, x, y)) {
-    shortest_distance = 0;
-
-  } else {
-    shortest_distance = m_polygon_shortest_distance (points, x, y, TRUE);
-  }
-
-  g_array_free (points, TRUE);
-
-  return shortest_distance;
+  return s_path_shortest_distance (object->path, x, y, solid);
 }
 
diff --git a/libgeda/src/o_picture.c b/libgeda/src/o_picture.c
index aa15b46..312e5ef 100644
--- a/libgeda/src/o_picture.c
+++ b/libgeda/src/o_picture.c
@@ -1021,13 +1021,15 @@ GdkPixbuf *o_picture_pixbuf_from_buffer (gchar *file_content,
  *
  *  Interrior points within the picture return a distance of zero.
  *
- *  \param [in] object  The picture OBJECT.
- *  \param [in] x       The x coordinate of the given point.
- *  \param [in] y       The y coordinate of the given point.
+ *  \param [in] object       The picture OBJECT.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
+ *  \param [in] force_solid  If true, force treating the object as solid.
  *  \return The shortest distance from the object to the point. With an
  *  invalid parameter, this function returns G_MAXDOUBLE.
  */
-double o_picture_shortest_distance (OBJECT *object, int x, int y)
+double o_picture_shortest_distance (OBJECT *object, int x, int y,
+                                    int force_solid)
 {
   double dx, dy;
   double x1, y1, x2, y2;
diff --git a/libgeda/src/o_text_basic.c b/libgeda/src/o_text_basic.c
index 43c22ad..55a1a48 100644
--- a/libgeda/src/o_text_basic.c
+++ b/libgeda/src/o_text_basic.c
@@ -1802,15 +1802,16 @@ void o_text_mirror_world(TOPLEVEL *toplevel,
  *  This function will calculate the distance to the text regardless
  *  if the text is visible or not.
  *
- *  \param [in] object  The text OBJECT.
- *  \param [in] x       The x coordinate of the given point.
- *  \param [in] y       The y coordinate of the given point.
+ *  \param [in] object       The text OBJECT.
+ *  \param [in] x            The x coordinate of the given point.
+ *  \param [in] y            The y coordinate of the given point.
+ *  \param [in] force_solid  If true, force treating the object as solid.
  *  \return The shortest distance from the object to the point. If the
  *  distance cannot be calculated, this function returns a really large
  *  number (G_MAXDOUBLE).  With an invalid parameter, this funciton
  *  returns G_MAXDOUBLE.
  */
-double o_text_shortest_distance (OBJECT *object, int x, int y)
+double o_text_shortest_distance (OBJECT *object, int x, int y, int force_solid)
 {
   double dx, dy;
 
diff --git a/libgeda/src/s_path.c b/libgeda/src/s_path.c
index ab94fef..3a52ba1 100644
--- a/libgeda/src/s_path.c
+++ b/libgeda/src/s_path.c
@@ -748,3 +748,40 @@ void s_path_to_polygon (PATH *path, GArray *points)
     }
   }
 }
+
+
+/*! \brief Calculates the distance between the given point and the closest
+ *  point on the given path segment.
+ *
+ *  \param [in] path    The path.
+ *  \param [in] x       The x coordinate of the given point.
+ *  \param [in] y       The y coordinate of the given point.
+ *  \param [in] solid   TRUE if the path should be treated as solid, FALSE if
+ *  the path should be treated as hollow.
+ *  \return The shortest distance from the path to the point.  With a solid
+ *  shape, this function returns a distance of zero for interior points.  With
+ *  an invalid parameter, this function returns G_MAXDOUBLE.
+ */
+double s_path_shortest_distance (PATH *path, int x, int y, int solid)
+{
+  double shortest_distance = G_MAXDOUBLE;
+  GArray *points;
+
+  points = g_array_new (FALSE, FALSE, sizeof (sPOINT));
+
+  s_path_to_polygon (path, points);
+
+  if (!solid) {
+    shortest_distance = m_polygon_shortest_distance (points, x, y, FALSE);
+
+  } else if (m_polygon_interior_point (points, x, y)) {
+    shortest_distance = 0;
+
+  } else {
+    shortest_distance = m_polygon_shortest_distance (points, x, y, TRUE);
+  }
+
+  g_array_free (points, TRUE);
+
+  return shortest_distance;
+}




_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs