Re: Canvas smooth lines?
- From: "Tuomas J. Lukka" <lukka fas harvard edu>
- To: Federico Mena Quintero <federico nuclecu unam mx>
- cc: gnome-list gnome org
- Subject: Re: Canvas smooth lines?
- Date: Sat, 27 Mar 1999 08:04:44 -0500 (EST)
On Thu, 25 Mar 1999, Federico Mena Quintero wrote:
> > Hi, I'm wondering if it is OK to touch the head branch of gnome-libs
> > to implement the smooth canvas lines (in gnome_canvas_line_point)?
> > I assume that the smooth_steps would cover the whole polyline (or would
> > it be only one segment)?
>
> If you want to do this, please do it as closely as possible as Tk does
> it. Basically it creates parabolic splines for each group of three
> points.
>
> If you implement this, would you mind if I take a look at the patch
> before putting it on cvs?
Oops, here's the patch.
Tuomas
? gnome-data/postscript.convert
? libgnorba/GnomeObject.h
? libgnorba/GnomeObject-common.c
? libgnorba/GnomeObject-stubs.c
? libgnorba/GnomeObject-skels.c
? libgnorba/Table.h
? libgnorba/Table-common.c
? libgnorba/Table-stubs.c
? libgnorba/Table-skels.c
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gnome-libs/ChangeLog,v
retrieving revision 1.390
diff -u -r1.390 ChangeLog
--- ChangeLog 1999/03/26 00:16:34 1.390
+++ ChangeLog 1999/03/27 13:02:35
@@ -1,3 +1,8 @@
+1999-03-27 Tuomas J. Lukka <lukka@iki.fi>
+
+ * implemented canvas splines
+
+
1999-03-25 Federico Mena Quintero <federico@nuclecu.unam.mx>
* configure.in: Bumped version number to 1.0.5.
Index: libgnomeui/gnome-canvas-line.c
===================================================================
RCS file: /cvs/gnome/gnome-libs/libgnomeui/gnome-canvas-line.c,v
retrieving revision 1.37
diff -u -r1.37 gnome-canvas-line.c
--- gnome-canvas-line.c 1999/01/18 17:50:16 1.37
+++ gnome-canvas-line.c 1999/03/27 13:02:36
@@ -181,6 +181,9 @@
if (line->coords)
g_free (line->coords);
+ if (line->orig_coords && line->orig_coords != line->coords)
+ g_free (line->orig_coords);
+
if (line->first_coords)
g_free (line->first_coords);
@@ -336,6 +339,101 @@
gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
}
+static void
+bezierpoints ( double cx[4], double cy[4], int n,
+ double *res )
+{
+ int i;
+ for(i=0; i<n; i++) {
+ double r = i/(double)n;
+ double r2 = r*r;
+ double r3 = r2*r;
+ double f = 1-r;
+ double f2 = f*f;
+ double f3 = f2*f;
+ res[0] = f3*cx[0] + 3*f2*r*cx[1] + 3*f*r2*cx[2] + r3*cx[3];
+ res[1] = f3*cy[0] + 3*f2*r*cy[1] + 3*f*r2*cy[2] + r3*cy[3];
+ res += 2;
+ }
+}
+
+static void
+reconfigure_smoothing (GnomeCanvasLine *line)
+{
+ int i;
+ double cx[4];
+ double cy[4];
+
+ if(!line->smooth || line->orig_num_points <= 2) {
+ line->num_points = line->orig_num_points;
+ line->coords = line->orig_coords;
+ return;
+ }
+ if (line->orig_num_points == 0) {
+ line->num_points = 0;
+ line->coords = NULL;
+ return;
+ }
+
+ /* Handle smoothed lines by generating an expanded set ot points */
+
+ /* We have spline_steps segments inside each original
+ * line segment, plus the end point
+ */
+ line->num_points = line->spline_steps * (line->orig_num_points - 2) + 1;
+ line->coords = g_malloc(2 * sizeof(*(line->coords)) * line->num_points);
+
+ /* Still need special case of closed lines */
+
+ for(i = 1; i < line->orig_num_points-1; i++) {
+ int ind = i*2;
+ /* Calculate control points */
+ if(i == 1) {
+ cx[0] = line->orig_coords[ind-2];
+ cy[0] = line->orig_coords[ind-1];
+ cx[1] = 1/3.0 * line->orig_coords[ind-2] +
+ 2/3.0 * line->orig_coords[ind];
+ cy[1] = 1/3.0 * line->orig_coords[ind-1] +
+ 2/3.0 * line->orig_coords[ind+1];
+ } else {
+ /* Default case: use the previous point */
+ cx[0] = 1/2.0 * line->orig_coords[ind-2] +
+ 1/2.0 * line->orig_coords[ind];
+ cy[0] = 1/2.0 * line->orig_coords[ind-1] +
+ 1/2.0 * line->orig_coords[ind+1];
+ cx[1] = 1/6.0 * line->orig_coords[ind-2] +
+ 5/6.0 * line->orig_coords[ind];
+ cy[1] = 1/6.0 * line->orig_coords[ind-1] +
+ 5/6.0 * line->orig_coords[ind+1];
+ }
+ if(i == line->orig_num_points-2) {
+ cx[2] = 2/3.0 * line->orig_coords[ind] +
+ 1/3.0 * line->orig_coords[ind+2];
+ cy[2] = 2/3.0 * line->orig_coords[ind+1] +
+ 1/3.0 * line->orig_coords[ind+3];
+ cx[3] = line->orig_coords[ind+2];
+ cy[3] = line->orig_coords[ind+3];
+ } else {
+ /* Default case: use the next point */
+ cx[2] = 5/6.0 * line->orig_coords[ind] +
+ 1/6.0 * line->orig_coords[ind+2];
+ cy[2] = 5/6.0 * line->orig_coords[ind+1] +
+ 1/6.0 * line->orig_coords[ind+3];
+ cx[3] = 1/2.0 * line->orig_coords[ind] +
+ 1/2.0 * line->orig_coords[ind+2];
+ cy[3] = 1/2.0 * line->orig_coords[ind+1] +
+ 1/2.0 * line->orig_coords[ind+3];
+ }
+ bezierpoints(cx, cy,
+ line->spline_steps,
+ line->coords + 2 * (i-1) * line->spline_steps
+ );
+ }
+ line->coords[2*(i-1)*line->spline_steps] = line->orig_coords[i*2];
+ line->coords[2*(i-1)*line->spline_steps+1] = line->orig_coords[i*2+1];
+
+}
+
/* Recalculates the arrow polygons for the line */
static void
reconfigure_arrows (GnomeCanvasLine *line)
@@ -563,6 +661,7 @@
static void
gnome_canvas_line_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
+ int smoothed;
GnomeCanvasItem *item;
GnomeCanvasLine *line;
GnomeCanvasPoints *points;
@@ -576,17 +675,25 @@
case ARG_POINTS:
points = GTK_VALUE_POINTER (*arg);
+ /* Discard both the smoothed and original coordinates */
+ smoothed = (line->coords != line->orig_coords);
if (line->coords) {
g_free (line->coords);
line->coords = NULL;
}
+ line->num_points = 0;
+ if (line->orig_coords && smoothed) {
+ g_free (line->orig_coords);
+ line->orig_coords = NULL;
+ }
+
if (!points)
- line->num_points = 0;
+ line->orig_num_points = 0;
else {
- line->num_points = points->num_points;
- line->coords = g_new (double, 2 * line->num_points);
- memcpy (line->coords, points->coords, 2 * line->num_points * sizeof (double));
+ line->orig_num_points = points->num_points;
+ line->orig_coords = g_new (double, 2 * line->orig_num_points);
+ memcpy (line->orig_coords, points->coords, 2 * line->orig_num_points * sizeof (double));
}
/* Drop the arrowhead polygons if they exist -- they will be regenerated */
@@ -720,13 +827,25 @@
break;
case ARG_SMOOTH:
- /* FIXME */
+ line->smooth = GTK_VALUE_BOOL (*arg);
+#ifdef OLD_XFORM
+ reconfigure_smoothing (line);
+#else
+ gnome_canvas_item_request_update (item);
+#endif
break;
case ARG_SPLINE_STEPS:
- /* FIXME */
+ line->smooth = GTK_VALUE_UINT (*arg);
+#ifdef OLD_XFORM
+ reconfigure_smoothing (line);
+#else
+ gnome_canvas_item_request_update (item);
+#endif
break;
+
+
case ARG_ARROW_SHAPE_A:
line->shape_a = fabs (GTK_VALUE_DOUBLE (*arg));
#ifdef OLD_XFORM
@@ -770,9 +889,9 @@
switch (arg_id) {
case ARG_POINTS:
- if (line->num_points != 0) {
- points = gnome_canvas_points_new (line->num_points);
- memcpy (points->coords, line->coords, 2 * line->num_points * sizeof (double));
+ if (line->orig_num_points != 0) {
+ points = gnome_canvas_points_new (line->orig_num_points);
+ memcpy (points->coords, line->orig_coords, 2 * line->orig_num_points * sizeof (double));
GTK_VALUE_POINTER (*arg) = points;
} else
GTK_VALUE_POINTER (*arg) = NULL;
@@ -909,6 +1028,7 @@
if (parent_class->update)
(* parent_class->update) (item, affine, clip_path, flags);
+ reconfigure_smoothing (line);
reconfigure_arrows (line);
if (item->canvas->aa) {
@@ -1130,15 +1250,9 @@
*actual_item = item;
best = 1.0e36;
-
- /* Handle smoothed lines by generating an expanded set ot points */
- if (line->smooth && (line->num_points > 2)) {
- /* FIXME */
- } else {
- num_points = line->num_points;
- line_points = line->coords;
- }
+ num_points = line->num_points;
+ line_points = line->coords;
/* Compute a polygon for each edge of the line and test the point against it. The effective
* width of the line is adjusted so that it will be at least one pixel thick (so that zero
Index: libgnomeui/gnome-canvas-line.h
===================================================================
RCS file: /cvs/gnome/gnome-libs/libgnomeui/gnome-canvas-line.h,v
retrieving revision 1.10
diff -u -r1.10 gnome-canvas-line.h
--- gnome-canvas-line.h 1999/01/01 07:51:39 1.10
+++ gnome-canvas-line.h 1999/03/27 13:02:36
@@ -78,7 +78,11 @@
* refer to the necks of the arrowheads rather than their tips. The
* actual endpoints are stored in the first_arrow and last_arrow
* arrays, if they exist.
+ * Smoothed coordinates are placed in this array
+ * although this may refer to the same memory as orig_coords
*/
+ int orig_num_points; /* Original number of points */
+ double * orig_coords; /* Original coordinates before smoothing */
double width; /* Width of the line */
Index: test-gnome/canvas-primitives.c
===================================================================
RCS file: /cvs/gnome/gnome-libs/test-gnome/canvas-primitives.c,v
retrieving revision 1.18
diff -u -r1.18 canvas-primitives.c
--- canvas-primitives.c 1999/03/26 12:37:45 1.18
+++ canvas-primitives.c 1999/03/27 13:02:38
@@ -623,6 +623,62 @@
}
static void
+setup_curves (GnomeCanvasGroup *root)
+{
+ GnomeCanvasPoints *points;
+
+ /* x: 400..600 y: 150..300 */
+ points = gnome_canvas_points_new (5);
+ points->coords[0] = 550.0;
+ points->coords[1] = 170.0;
+ points->coords[2] = 450.0;
+ points->coords[3] = 170.0;
+ points->coords[4] = 400.0;
+ points->coords[5] = 230.0;
+ points->coords[6] = 450.0;
+ points->coords[7] = 270.0;
+ points->coords[8] = 550.0;
+ points->coords[9] = 270.0;
+ setup_item (gnome_canvas_item_new (root,
+ gnome_canvas_line_get_type (),
+ "points", points,
+ "fill_color", "black",
+ "width_units", 8.0,
+ "first_arrowhead", TRUE,
+ "last_arrowhead", TRUE,
+ "arrow_shape_a", 8.0,
+ "arrow_shape_b", 12.0,
+ "arrow_shape_c", 4.0,
+ "smooth", TRUE,
+ NULL));
+ gnome_canvas_points_free (points);
+
+ points = gnome_canvas_points_new (5);
+ points->coords[0] = 550.0;
+ points->coords[1] = 170.0;
+ points->coords[2] = 450.0;
+ points->coords[3] = 170.0;
+ points->coords[4] = 400.0;
+ points->coords[5] = 230.0;
+ points->coords[6] = 450.0;
+ points->coords[7] = 270.0;
+ points->coords[8] = 550.0;
+ points->coords[9] = 270.0;
+ setup_item (gnome_canvas_item_new (root,
+ gnome_canvas_line_get_type (),
+ "points", points,
+ "fill_color", "white",
+ "width_units", 2.0,
+ "first_arrowhead", TRUE,
+ "last_arrowhead", TRUE,
+ "arrow_shape_a", 8.0,
+ "arrow_shape_b", 12.0,
+ "arrow_shape_c", 4.0,
+ NULL));
+ gnome_canvas_points_free (points);
+}
+
+static void
setup_polygons (GnomeCanvasGroup *root)
{
GnomeCanvasPoints *points;
@@ -780,6 +836,7 @@
setup_texts (root);
setup_images (root, aa);
setup_lines (root);
+ setup_curves (root);
setup_polygons (root);
setup_widgets (root);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]