⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stroke.c

📁 添加系统调用。。。在LINUX下添加一个新的系统调用。在文件中添加自己的系统调用的源代码
💻 C
字号:
/*cellwriter -- a character recognition input methodCopyright (C) 2007 Michael Levin <risujin@risujin.org>This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/#include "config.h"#include <string.h>#include <math.h>#include <gtk/gtk.h>#include "common.h"#include "recognize.h"/*        Stroke functions*//* Distance from the line formed by the two neighbors of a point, which, if   not exceeded, will cause the point to be culled during simplification */#define SIMPLIFY_THRESHOLD 0.5/* Granularity of stroke point array in points */#define POINTS_GRAN 64/* Size of a stroke structure */#define STROKE_SIZE(size) (sizeof (Stroke) + (size) * sizeof (Point))void process_stroke(Stroke *stroke)/* Generate cached parameters of a stroke */{        int i;        float distance;        if (stroke->processed)                return;        stroke->processed = TRUE;        /* Dot strokes */        if (stroke->len == 1) {                vec2_set(&stroke->center, stroke->points[0].x,                         stroke->points[0].y);                stroke->spread = 0.f;                return;        }        stroke->min_x = stroke->max_x = stroke->points[0].x;        stroke->min_y = stroke->max_y = stroke->points[0].y;        for (i = 0, distance = 0.; i < stroke->len - 1; i++) {                Vec2 v;                float weight;                /* Angle */                vec2_set(&v, stroke->points[i + 1].x - stroke->points[i].x,                         stroke->points[i + 1].y - stroke->points[i].y);                stroke->points[i].angle = vec2_angle(&v);                /* Point contribution to spread */                if (stroke->points[i + 1].x < stroke->min_x)                        stroke->min_x = stroke->points[i + 1].x;                if (stroke->points[i + 1].y < stroke->min_y)                        stroke->min_y = stroke->points[i + 1].y;                if (stroke->points[i + 1].x > stroke->max_x)                        stroke->max_x = stroke->points[i + 1].x;                if (stroke->points[i + 1].y > stroke->max_y)                        stroke->max_y = stroke->points[i + 1].y;                /* Segment contribution to center */                vec2_set(&v, stroke->points[i + 1].x - stroke->points[i].x,                         stroke->points[i + 1].y - stroke->points[i].y);                distance += weight = vec2_mag(&v);                vec2_set(&v, stroke->points[i + 1].x + stroke->points[i].x,                         stroke->points[i + 1].y + stroke->points[i].y);                vec2_scale(&v, &v, weight / 2.);                vec2_sum(&stroke->center, &stroke->center, &v);        }        vec2_scale(&stroke->center, &stroke->center, 1. / distance);        stroke->points[i].angle = stroke->points[i - 1].angle;        stroke->distance = distance;        /* Stroke spread */        stroke->spread = stroke->max_x - stroke->min_x;        if (stroke->max_y - stroke->min_y > stroke->spread)                stroke->spread = stroke->max_y - stroke->min_y;}void clear_stroke(Stroke *stroke)/* Clear cached parameters */{        int size;        size = stroke->size;        memset(stroke, 0, sizeof (*stroke));        stroke->size = size;}Stroke *stroke_new(int size)/* Allocate memory for a new stroke */{        Stroke *stroke;        if (size < POINTS_GRAN)                size = POINTS_GRAN;        stroke = g_malloc(STROKE_SIZE(size));        stroke->size = size;        clear_stroke(stroke);        return stroke;}static void reverse_copy_points(Point *dest, const Point *src, int len){        int i;        for (i = 0; i < len; i++) {                ANGLE angle = 0;                if (i < len - 1)                        angle = src[len - i - 2].angle + ANGLE_PI;                dest[i] = src[len - i - 1];                dest[i].angle = angle;        }}Stroke *stroke_clone(const Stroke *src, int reverse){        Stroke *stroke;        if (!src)                return NULL;        stroke = stroke_new(src->size);        if (!reverse)                memcpy(stroke, src, STROKE_SIZE(src->size));        else {                memcpy(stroke, src, sizeof (Stroke));                reverse_copy_points(stroke->points, src->points, src->len);        }        return stroke;}void stroke_free(Stroke *stroke){        g_free(stroke);}void glue_stroke(Stroke **pa, const Stroke *b, int reverse)/* Glue B onto the end of A preserving processed properties */{        Vec2 glue_seg, glue_center, b_center;        Point start;        Stroke *a;        float glue_mag;        a = *pa;        /* If there is no stroke to glue to, just copy */        if (!a || a->len < 1) {                *pa = stroke_clone(b, reverse);                return;        }        /* Allocate memory */        if (a->size < a->len + b->len) {                a->size = a->len + b->len;                a = g_realloc(a, STROKE_SIZE(a->size));        }        /* Gluing two strokes creates a new segment between them */        start = reverse ? b->points[b->len - 1] : b->points[0];        vec2_set(&glue_seg, start.x - a->points[a->len - 1].x,                 start.y - a->points[a->len - 1].y);        vec2_set(&glue_center, (start.x + a->points[a->len - 1].x) / 2,                 (start.y + a->points[a->len - 1].y) / 2);        glue_mag = vec2_mag(&glue_seg);        /* Compute new spread */        if (b->min_x < a->min_x)                a->min_x = b->min_x;        if (b->max_x > a->max_x)                a->max_x = b->max_x;        if (b->min_y < a->min_y)                a->min_y = b->min_y;        if (b->max_y > a->max_y)                a->max_y = b->max_y;        a->spread = a->max_x - a->min_x;        if (a->max_y - a->min_y > a->spread)                a->spread = a->max_y - a->min_y;        /* Compute new center point */        vec2_scale(&a->center, &a->center, a->distance);        vec2_scale(&b_center, &b->center, b->distance);        vec2_scale(&glue_center, &glue_center, glue_mag);        vec2_set(&a->center, a->center.x + b_center.x + glue_center.x,                 a->center.y + b_center.y + glue_center.y);        vec2_scale(&a->center, &a->center,                   1.f / (a->distance + b->distance + glue_mag));        /* Copy points */        if (!reverse || b->len < 2)                memcpy(a->points + a->len, b->points, b->len * sizeof (Point));        else                reverse_copy_points(a->points + a->len, b->points, b->len);        a->points[a->len - 1].angle = vec2_angle(&glue_seg);        a->distance += glue_mag + b->distance;        a->len += b->len;        *pa = a;}void draw_stroke(Stroke **ps, int x, int y)/* Add a point in scaled coordinates to a stroke */{        /* Create a new stroke if necessary */        if (!(*ps))                *ps = stroke_new(0);        /* If we run out of room, resample the stroke to fit */        if ((*ps)->len >= POINTS_MAX) {                Stroke *new_stroke;                new_stroke = sample_stroke(NULL, *ps, POINTS_MAX - POINTS_GRAN,                                           POINTS_MAX);                stroke_free(*ps);                *ps = new_stroke;        }        /* Range limits */        if (x <= -SCALE / 2)                x = -SCALE / 2 + 1;        if (x >= SCALE / 2)                x = SCALE / 2 - 1;        if (y <= -SCALE / 2)                y = -SCALE / 2 + 1;        if (y >= SCALE / 2)                y = SCALE / 2 - 1;        /* Do we need more memory? */        if ((*ps)->len >= (*ps)->size) {                (*ps)->size += POINTS_GRAN;                *ps = g_realloc(*ps, STROKE_SIZE((*ps)->size));        }        (*ps)->points[(*ps)->len].x = x;        (*ps)->points[(*ps)->len++].y = y;}void smooth_stroke(Stroke *s)/* Smooth stroke points by moving each point halfway toward the line between   its two neighbors */{        int i, last_x, last_y;        last_x = s->points[0].x;        last_y = s->points[0].y;        for (i = 1; i < s->len - 1; i++) {                Vec2 a, b, c, m, ab, ac, am;                if (last_x == s->points[i + 1].x &&                    last_y == s->points[i + 1].y) {                        last_x = s->points[i].x;                        last_y = s->points[i].y;                        continue;                }                vec2_set(&a, last_x, last_y);                vec2_set(&b, s->points[i].x, s->points[i].y);                vec2_set(&c, s->points[i + 1].x, s->points[i + 1].y);                vec2_sub(&ac, &c, &a);                vec2_sub(&ab, &b, &a);                vec2_proj(&am, &ab, &ac);                vec2_sum(&m, &a, &am);                vec2_avg(&b, &b, &m, 0.5);                last_x = s->points[i].x;                last_y = s->points[i].y;                s->points[i].x = b.x + 0.5;                s->points[i].y = b.y + 0.5;        }}void simplify_stroke(Stroke *s)/* Remove excess points between neighbors */{	int i;	for (i = 1; i < s->len - 1; i++) {	        Vec2 l, w;		double dist, mag, dot;                /* Vector l is a unit vector from point i - 1 to point i + 1 */		vec2_set(&l, s->points[i - 1].x - s->points[i + 1].x,		         s->points[i - 1].y - s->points[i + 1].y);		mag = vec2_norm(&l, &l);		/* Vector w is a vector from point i - 1 to point i */		vec2_set(&w, s->points[i - 1].x - s->points[i].x,		         s->points[i - 1].y - s->points[i].y);		/* Do not touch mid points that are not in between their		   neighbors */		dot = vec2_dot(&l, &w);		if (dot < 0. || dot > mag)		        continue;		/* Remove any points that are less than some threshold away		   from their neighbor points */		dist = vec2_cross(&w, &l);		if (dist < SIMPLIFY_THRESHOLD && dist > -SIMPLIFY_THRESHOLD) {			memmove(s->points + i, s->points + i + 1,			        (--s->len - i) * sizeof (*s->points));			i--;		}	}}void dump_stroke(Stroke *stroke){        int i;        /* Print stats */        g_message("Stroke data --");        g_debug("Distance: %g", stroke->distance);        g_debug("  Center: (%g, %g)", stroke->center.x, stroke->center.y);        g_debug("  Spread: %d", stroke->spread);        g_message("%d points --", stroke->len);        /* Print point data */        for (i = 0; i < stroke->len; i++)                g_debug("%3d: (%4d,%4d)\n",                        i, stroke->points[i].x, stroke->points[i].y);}Stroke *sample_stroke(Stroke *out, Stroke *in, int points, int size)/* Recreate the stroke by sampling at regular distance intervals.   Sampled strokes always have angle data. */{        Vec2 v;        double dist_i, dist_j, dist_per;        int i, j, len;        if (!in || in->len < 1) {                g_warning("Attempted to sample an invalid stroke");                return NULL;        }        /* Check ranges */        if (size >= POINTS_MAX) {                g_warning("Stroke sized to maximum length possible");                size = POINTS_MAX;        }        if (points >= POINTS_MAX) {                g_warning("Stroke sampled to maximum length possible");                points = POINTS_MAX;        }        if (size < 1)                size = 1;        if (points < 1)                points = 1;        /* Allocate memory and copy cached data */        if (!out)                out = g_malloc(STROKE_SIZE(size));        out->size = size;        len = out->size < points ? out->size - 1 : points - 1;        out->len = len + 1;        out->spread = in->spread;        out->center = in->center;        /* Special case for sampling a single point */        if (in->len <= 1 || points <= 1) {                for (i = 0; i < len + 1; i++)                        out->points[i] = in->points[0];                out->distance = 0.;                return out;        }        dist_per = in->distance / (points - 1);        out->distance = in->distance;        vec2_set(&v, in->points[1].x - in->points[0].x,                 in->points[1].y - in->points[0].y);        dist_j = vec2_mag(&v);        dist_i = dist_per;        out->points[0] = in->points[0];        for (i = 1, j = 0; i < len; i++) {                /* Advance our position */                while (dist_i >= dist_j) {                        if (j >= in->len - 2)                                goto finish;                        dist_i -= dist_j;                        j++;                        vec2_set(&v, in->points[j + 1].x - in->points[j].x,                                 in->points[j + 1].y - in->points[j].y);                        dist_j = vec2_mag(&v);                }                /* Interpolate points */                out->points[i].x = in->points[j].x +                                   (in->points[j + 1].x - in->points[j].x) *                                   dist_i / dist_j;                out->points[i].y = in->points[j].y +                                   (in->points[j + 1].y - in->points[j].y) *                                   dist_i / dist_j;                out->points[i].angle = in->points[j].angle;                dist_i += dist_per;        }finish:        for (; i < len + 1; i++)                out->points[i] = in->points[j + 1];        return out;}void sample_strokes(Stroke *a, Stroke *b, Stroke **as, Stroke **bs)/* Sample multiple strokes to equal lengths */{        double dist;        int points;        /* Find the sample length */        dist = a->distance;        if (b->distance > dist)                dist = b->distance;        points = 1 + dist / FINE_RESOLUTION;        if (points > POINTS_MAX)                points = POINTS_MAX;        *as = sample_stroke(NULL, a, points, points);        *bs = sample_stroke(NULL, b, points, points);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -