app/vectors/gimpstroke.[ch] Applied a modified patch from Geert Jordaens

2004-06-30  Simon Budig  <simon@gimp.org>

	* app/vectors/gimpstroke.[ch]
	* tools/pdbgen/pdb/paths.pdb: Applied a modified patch from
	Geert Jordaens that implements the gimp-path-get-point-at-dist
	PDB function (fixes bug #138754).

	* app/pdb/paths_cmds.c: regenerated
This commit is contained in:
Simon Budig 2004-06-29 22:45:58 +00:00 committed by Simon Budig
parent 3cec641627
commit 2cf661fc16
5 changed files with 220 additions and 17 deletions

View File

@ -1,3 +1,12 @@
2004-06-30 Simon Budig <simon@gimp.org>
* app/vectors/gimpstroke.[ch]
* tools/pdbgen/pdb/paths.pdb: Applied a modified patch from
Geert Jordaens that implements the gimp-path-get-point-at-dist
PDB function (fixes bug #138754).
* app/pdb/paths_cmds.c: regenerated
2004-06-30 Michael Natterer <mitch@gimp.org>
* app/widgets/gimptoolbox.c (gimp_toolbox_button_accel_changed):

View File

@ -655,6 +655,11 @@ path_get_point_at_dist_invoker (Gimp *gimp,
gint32 y_point = 0;
gdouble gradient = 0;
GimpVectors *vectors;
GimpStroke *stroke;
gdouble distance_along;
gdouble stroke_length;
gdouble stroke_distance;
GimpCoords position;
gimage = gimp_image_get_by_ID (gimp, args[0].value.pdb_int);
if (! GIMP_IS_IMAGE (gimage))
@ -668,11 +673,44 @@ path_get_point_at_dist_invoker (Gimp *gimp,
if (vectors)
{
g_warning ("FIXME: path_get_point_at_dist() is unimplemented");
success = FALSE;
distance_along = 0.0;
stroke = gimp_vectors_stroke_get_next (vectors, NULL);
while (stroke != NULL )
{
stroke_length = gimp_stroke_get_length (stroke, 0.5);
if (distance_along + stroke_length < distance)
{
distance_along += stroke_length;
}
else
{
stroke_distance = distance - distance_along;
stroke_distance = stroke_distance < 0 ? 0: stroke_distance;
if (!gimp_stroke_get_point_at_dist (stroke, stroke_distance, 0.5,
&position, &gradient))
{
success = FALSE;
break;
}
else
{
success = TRUE;
x_point = ROUND (position.x);
y_point = ROUND (position.y);
break;
}
}
stroke = gimp_vectors_stroke_get_next (vectors, stroke);
}
}
else
success = FALSE;
{
success = FALSE;
}
}
return_args = procedural_db_return_args (&path_get_point_at_dist_proc, success);

View File

@ -26,6 +26,7 @@
#include "vectors-types.h"
#include "core/gimp-utils.h"
#include "core/gimpcoords.h"
#include "gimpanchor.h"
#include "gimpstroke.h"
@ -126,7 +127,8 @@ gboolean gimp_stroke_real_connect_stroke (GimpStroke *stroke,
static gboolean gimp_stroke_real_is_empty (const GimpStroke *stroke);
static gdouble gimp_stroke_real_get_length (const GimpStroke *stroke);
static gdouble gimp_stroke_real_get_length (const GimpStroke *stroke,
const gdouble precision);
static gdouble gimp_stroke_real_get_distance (const GimpStroke *stroke,
const GimpCoords *coord);
static GArray * gimp_stroke_real_interpolate (const GimpStroke *stroke,
@ -149,6 +151,11 @@ static GList * gimp_stroke_real_get_draw_controls (const GimpStroke *stroke);
static GArray * gimp_stroke_real_get_draw_lines (const GimpStroke *stroke);
static GArray * gimp_stroke_real_control_points_get (const GimpStroke *stroke,
gboolean *ret_closed);
static gboolean gimp_stroke_real_get_point_at_dist (const GimpStroke *stroke,
const gdouble dist,
const gdouble precision,
GimpCoords *position,
gdouble *gradient);
/* private variables */
@ -230,6 +237,7 @@ gimp_stroke_class_init (GimpStrokeClass *klass)
klass->is_empty = gimp_stroke_real_is_empty;
klass->get_length = gimp_stroke_real_get_length;
klass->get_distance = gimp_stroke_real_get_distance;
klass->get_point_at_dist = gimp_stroke_real_get_point_at_dist;
klass->interpolate = gimp_stroke_real_interpolate;
klass->duplicate = gimp_stroke_real_duplicate;
@ -849,19 +857,45 @@ gimp_stroke_real_is_empty (const GimpStroke *stroke)
gdouble
gimp_stroke_get_length (const GimpStroke *stroke)
gimp_stroke_get_length (const GimpStroke *stroke,
const gdouble precision)
{
g_return_val_if_fail (GIMP_IS_STROKE (stroke), 0.0);
return GIMP_STROKE_GET_CLASS (stroke)->get_length (stroke);
return GIMP_STROKE_GET_CLASS (stroke)->get_length (stroke, precision);
}
static gdouble
gimp_stroke_real_get_length (const GimpStroke *stroke)
gimp_stroke_real_get_length (const GimpStroke *stroke,
const gdouble precision)
{
g_printerr ("gimp_stroke_get_length: default implementation\n");
GArray *points;
gint i;
gdouble length;
GimpCoords difference;
return 0.0;
g_return_val_if_fail (GIMP_IS_STROKE (stroke), -1);
if (!stroke->anchors)
return -1;
points = gimp_stroke_interpolate (stroke, precision, NULL);
if (points == NULL)
return -1;
length = 0;
for (i = 0; i < points->len - 1; i++ )
{
gimp_coords_difference (&(g_array_index (points, GimpCoords, i)),
&(g_array_index (points, GimpCoords, i+1)),
&difference);
length += gimp_coords_length (&difference);
}
g_array_free(points, TRUE);
return length;
}
@ -1190,3 +1224,78 @@ gimp_stroke_real_control_points_get (const GimpStroke *stroke,
return ret_array;
}
gboolean
gimp_stroke_get_point_at_dist (const GimpStroke *stroke,
const gdouble dist,
const gdouble precision,
GimpCoords *position,
gdouble *gradient)
{
g_return_val_if_fail (GIMP_IS_STROKE (stroke), FALSE);
return GIMP_STROKE_GET_CLASS (stroke)->get_point_at_dist (stroke,
dist,
precision,
position,
gradient);
}
static gboolean
gimp_stroke_real_get_point_at_dist (const GimpStroke *stroke,
const gdouble dist,
const gdouble precision,
GimpCoords *position,
gdouble *gradient)
{
GArray *points;
gint i;
gdouble length;
gdouble segment_length;
gboolean ret = FALSE;
GimpCoords difference;
g_return_val_if_fail (GIMP_IS_STROKE (stroke), FALSE);
points = gimp_stroke_interpolate (stroke, precision, NULL);
if (points == NULL)
return ret;
length = 0;
for (i=0; i < points->len - 1; i++)
{
gimp_coords_difference (&(g_array_index (points, GimpCoords , i)),
&(g_array_index (points, GimpCoords , i+1)),
&difference);
segment_length = gimp_coords_length (&difference);
if (segment_length == 0 || length + segment_length < dist )
{
length += segment_length;
}
else
{
/* x = x1 + (x2 - x1 ) u */
/* x = x1 (1-u) + u x2 */
gdouble u = (dist - length) / segment_length;
gimp_coords_mix (1 - u, &(g_array_index (points, GimpCoords , i)),
u, &(g_array_index (points, GimpCoords , i+1)),
position);
if (difference.y == 0)
*gradient = G_MAXDOUBLE;
else
*gradient = difference.x / difference.y;
ret = TRUE;
break;
}
}
g_array_free (points, TRUE);
return ret;
}

View File

@ -115,9 +115,15 @@ struct _GimpStrokeClass
GimpAnchor *neighbor);
gboolean (* is_empty) (const GimpStroke *stroke);
gdouble (* get_length) (const GimpStroke *stroke);
gdouble (* get_length) (const GimpStroke *stroke,
const gdouble precision);
gdouble (* get_distance) (const GimpStroke *stroke,
const GimpCoords *coord);
gboolean (* get_point_at_dist) (const GimpStroke *stroke,
const gdouble dist,
const gdouble precision,
GimpCoords *position,
gdouble *gradient);
GArray * (* interpolate) (const GimpStroke *stroke,
const gdouble precision,
@ -237,13 +243,20 @@ gboolean gimp_stroke_is_empty (const GimpStroke *stroke);
/* accessing the shape of the curve */
gdouble gimp_stroke_get_length (const GimpStroke *stroke);
gdouble gimp_stroke_get_length (const GimpStroke *stroke,
const gdouble precision);
gdouble gimp_stroke_get_distance (const GimpStroke *stroke,
const GimpCoords *coord);
gboolean gimp_stroke_get_point_at_dist (const GimpStroke *stroke,
const gdouble dist,
const gdouble precision,
GimpCoords *position,
gdouble *gradient);
/* returns an array of valid coordinates */
GArray * gimp_stroke_interpolate (const GimpStroke *stroke,
gdouble precision,
const gdouble precision,
gboolean *closed);
GimpStroke * gimp_stroke_duplicate (const GimpStroke *stroke);
@ -265,6 +278,5 @@ GList * gimp_stroke_get_draw_anchors (const GimpStroke *stroke);
GList * gimp_stroke_get_draw_controls (const GimpStroke *stroke);
GArray * gimp_stroke_get_draw_lines (const GimpStroke *stroke);
#endif /* __GIMP_STROKE_H__ */

View File

@ -353,18 +353,53 @@ HELP
);
%invoke = (
vars => [ 'GimpVectors *vectors' ],
vars => [ 'GimpVectors *vectors', 'GimpStroke *stroke',
'gdouble distance_along', 'gdouble stroke_length',
'gdouble stroke_distance', 'GimpCoords position' ],
code => <<'CODE'
{
vectors = gimp_image_get_active_vectors (gimage);
if (vectors)
{
g_warning ("FIXME: path_get_point_at_dist() is unimplemented");
success = FALSE;
distance_along = 0.0;
stroke = gimp_vectors_stroke_get_next (vectors, NULL);
while (stroke != NULL )
{
stroke_length = gimp_stroke_get_length (stroke, 0.5);
if (distance_along + stroke_length < distance)
{
distance_along += stroke_length;
}
else
{
stroke_distance = distance - distance_along;
stroke_distance = stroke_distance < 0 ? 0: stroke_distance;
if (!gimp_stroke_get_point_at_dist (stroke, stroke_distance, 0.5,
&position, &gradient))
{
success = FALSE;
break;
}
else
{
success = TRUE;
x_point = ROUND (position.x);
y_point = ROUND (position.y);
break;
}
}
stroke = gimp_vectors_stroke_get_next (vectors, stroke);
}
}
else
success = FALSE;
{
success = FALSE;
}
}
CODE
);