home *** CD-ROM | disk | FTP | other *** search
- /* airbrush_blob.c: routines for manipulating scan converted convex
- * polygons.
- *
- * Copyright 1998-1999, Owen Taylor <otaylor@gtk.org>
- *
- * > Please contact the above author before modifying the copy <
- * > of this file in the GIMP distribution. Thanks. <
- *
- * 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-1307, USA.
- */
-
- #include <glib.h>
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <libgimp/gimpmath.h>
-
- #include "airbrush_blob.h"
-
-
- #define SUBSAMPLE 8.0
- #define SU 8.0
-
-
- static AirBrushBlob *
- airbrush_blob_new (int y, int height)
- {
-
- AirBrushBlob *result;
-
- result = g_malloc (sizeof (AirBrushBlob) + sizeof(AirBrushBlobSpan) * (height-1));
- result->y = y;
- result->height = height;
- return result;
- }
-
-
- static AirBlob *
- airblob_new(int y)
- {
- AirBlob *result;
-
- result = g_malloc (sizeof (AirBlob));
- return result;
- }
-
- static AirLine *
- airline_new(int y)
- {
- AirLine *result;
-
- result = g_malloc(sizeof (AirLine));
- return result;
- }
-
-
-
-
-
- typedef enum {
- EDGE_NONE = 0,
- EDGE_LEFT = 1 << 0,
- EDGE_RIGHT = 1 << 1
- } EdgeType;
-
- static void
- airbrush_blob_fill (AirBrushBlob *b, EdgeType *present)
- {
-
- int start;
- int x1, x2, i1, i2;
- int i;
-
- /* Mark empty lines at top and bottom as unused */
-
- start = 0;
- while (!(present[start]))
- {
- b->data[start].left = 0;
- b->data[start].right = -1;
- start++;
- }
- if (present[start] != (EDGE_RIGHT | EDGE_LEFT))
- {
- if (present[start] == EDGE_RIGHT)
- b->data[start].left = b->data[start].right;
- else
- b->data[start].right = b->data[start].left;
-
- present[start] = EDGE_RIGHT | EDGE_LEFT;
- }
-
- for (i=b->height-1;!present[i];i--)
- {
- b->data[i].left = 0;
- b->data[i].right = -1;
- }
- if (present[i] != (EDGE_RIGHT | EDGE_LEFT))
- {
- if (present[i] == EDGE_RIGHT)
- b->data[i].left = b->data[i].right;
- else
- b->data[i].right = b->data[i].left;
-
- present[i] = EDGE_RIGHT | EDGE_LEFT;
- }
-
-
- /* Restore missing edges */
-
- /* We fill only interior regions of convex hull, as if we were filling
- polygons. But since we draw ellipses with nearest points, not interior
- points, maybe it would look better if we did the same here. Probably
- not a big deal either way after anti-aliasing */
-
- /* left edge */
- for (i1=start; i1<b->height-2; i1++)
- {
- /* Find empty gaps */
- if (!(present[i1+1] & EDGE_LEFT))
- {
- int increment; /* fractional part */
- int denom; /* denominator of fraction */
- int step; /* integral step */
- int frac; /* fractional step */
- int reverse;
-
- /* find bottom of gap */
- i2 = i1+2;
- while (!(present[i2] & EDGE_LEFT) && i2 < b->height) i2++;
-
- if (i2 < b->height)
- {
- denom = i2-i1;
- x1 = b->data[i1].left;
- x2 = b->data[i2].left;
- step = (x2-x1)/denom;
- frac = x2-x1 - step*denom;
- if (frac < 0)
- {
- frac = -frac;
- reverse = 1;
- }
- else
- reverse = 0;
-
- increment = 0;
- for (i=i1+1; i<i2; i++)
- {
- x1 += step;
- increment += frac;
- if (increment >= denom)
- {
- increment -= denom;
- x1 += reverse ? -1 : 1;
- }
- if (increment == 0 || reverse)
- b->data[i].left = x1;
- else
- b->data[i].left = x1 + 1;
- }
- }
- i1 = i2-1; /* advance to next possibility */
- }
- }
-
- /* right edge */
- for (i1=start; i1<b->height-2; i1++)
- {
- /* Find empty gaps */
- if (!(present[i1+1] & EDGE_RIGHT))
- {
- int increment; /* fractional part */
- int denom; /* denominator of fraction */
- int step; /* integral step */
- int frac; /* fractional step */
- int reverse;
-
- /* find bottom of gap */
- i2 = i1+2;
- while (!(present[i2] & EDGE_RIGHT) && i2 < b->height) i2++;
-
- if (i2 < b->height)
- {
- denom = i2-i1;
- x1 = b->data[i1].right;
- x2 = b->data[i2].right;
- step = (x2-x1)/denom;
- frac = x2-x1 - step*denom;
- if (frac < 0)
- {
- frac = -frac;
- reverse = 1;
- }
- else
- reverse = 0;
-
- increment = 0;
- for (i=i1+1; i<i2; i++)
- {
- x1 += step;
- increment += frac;
- if (increment >= denom)
- {
- increment -= denom;
- x1 += reverse ? -1 : 1;
- }
- if (reverse && increment != 0)
- b->data[i].right = x1 - 1;
- else
- b->data[i].right = x1;
- }
- }
- i1 = i2-1; /* advance to next possibility */
- }
- }
-
- }
-
- static void
- airbrush_blob_make_convex (AirBrushBlob *b, EdgeType *present)
- {
- int x1, x2, y1, y2, i1, i2;
- int i;
- int start;
-
- /* Walk through edges, deleting points that aren't on convex hull */
-
- start = 0;
- while (!(present[start])) start++;
-
- /* left edge */
-
- i1 = start-1;
- i2 = start;
- x1 = b->data[start].left - b->data[start].right;
- y1 = 0;
-
- for (i=start+1;i<b->height;i++)
- {
- if (!(present[i] & EDGE_LEFT))
- continue;
-
- x2 = b->data[i].left - b->data[i2].left;
- y2 = i-i2;
-
- while (x2*y1 - x1*y2 < 0) /* clockwise rotation */
- {
- present[i2] &= ~EDGE_LEFT;
- i2 = i1;
- while (!(present[--i1] & EDGE_LEFT) && i1>=start);
-
- if (i1<start)
- {
- x1 = b->data[start].left - b->data[start].right;
- y1 = 0;
- }
- else
- {
- x1 = b->data[i2].left - b->data[i1].left;
- y1 = i2 - i1;
- }
- x2 = b->data[i].left - b->data[i2].left;
- y2 = i - i2;
- }
- x1 = x2;
- y1 = y2;
- i1 = i2;
- i2 = i;
- }
-
- /* Right edge */
-
- i1 = start -1;
- i2 = start;
- x1 = b->data[start].right - b->data[start].left;
- y1 = 0;
-
- for (i=start+1;i<b->height;i++)
- {
- if (!(present[i] & EDGE_RIGHT))
- continue;
-
- x2 = b->data[i].right - b->data[i2].right;
- y2 = i-i2;
-
- while (x2*y1 - x1*y2 > 0) /* counter-clockwise rotation */
- {
- present[i2] &= ~EDGE_RIGHT;
- i2 = i1;
- while (!(present[--i1] & EDGE_RIGHT) && i1>=start);
-
- if (i1<start)
- {
- x1 = b->data[start].right - b->data[start].left;
- y1 = 0;
- }
- else
- {
- x1 = b->data[i2].right - b->data[i1].right;
- y1 = i2 - i1;
- }
- x2 = b->data[i].right - b->data[i2].right;
- y2 = i - i2;
- }
- x1 = x2;
- y1 = y2;
- i1 = i2;
- i2 = i;
- }
-
- airbrush_blob_fill (b, present);
- }
-
- AirBrushBlob *
- airbrush_blob_convex_union (AirBrushBlob *b1, AirBrushBlob *b2)
- {
- AirBrushBlob *result;
- int y;
- int i, j;
- EdgeType *present;
-
-
- /* Create the storage for the result */
-
- y = MIN(b1->y,b2->y);
- result = airbrush_blob_new (y, MAX(b1->y+b1->height,b2->y+b2->height)-y);
-
- if (result->height == 0)
- return result;
-
- present = g_new0 (EdgeType, result->height);
-
- /* Initialize spans from original objects */
-
- for (i=0, j=b1->y-y; i<b1->height; i++,j++)
- {
- if (b1->data[i].right >= b1->data[i].left)
- {
- present[j] = EDGE_LEFT | EDGE_RIGHT;
- result->data[j].left = b1->data[i].left;
- result->data[j].right = b1->data[i].right;
- }
- }
-
- for (i=0, j=b2->y-y; i<b2->height; i++,j++)
- {
- if (b2->data[i].right >= b2->data[i].left)
- {
- if (present[j])
- {
- if (result->data[j].left > b2->data[i].left)
- result->data[j].left = b2->data[i].left;
- if (result->data[j].right < b2->data[i].right)
- result->data[j].right = b2->data[i].right;
- }
- else
- {
- present[j] = EDGE_LEFT | EDGE_RIGHT;
- result->data[j].left = b2->data[i].left;
- result->data[j].right = b2->data[i].right;
- }
- }
- }
-
- airbrush_blob_make_convex (result, present);
-
- g_free (present);
- return result;
- }
-
- /* You must be able to divide TABLE_SIZE with 4*/
-
- #define TABLE_SIZE 256
- #define TABLE_QUARTER TABLE_SIZE/4
-
- #define ELLIPSE_SHIFT 2
- #define TABLE_SHIFT 14
- #define TOTAL_SHIFT (ELLIPSE_SHIFT + TABLE_SHIFT)
-
- static int trig_initialized = 0;
- static int trig_table[TABLE_SIZE];
- #define POWFAC 0.999
-
-
-
- /* Scan convert an ellipse specified by _offsets_ of major and
- minor axes, and by center into a airbrush_blob */
-
- /* Warning UGLY code ahead :-)*/
-
- AirBrushBlob *
- airbrush_blob_ellipse (double xc, double yc, double xt, double yt, double xr, double yr, double xb, double yb, double xl, double yl)
- {
- int i;
- AirBrushBlob *rma, *rmi, *rtot;
- gint maxyma, minyma, maxymi, minymi;
- gint step;
- double max_radius;
- double ma_ang1, ma_ang2;
- double x1, x2, y1, y2;
- double xtotma, ytotma;
- double xcma, ycma, ytma, xrma, ybma, xlma;
- double xcmi, ycmi, ytmi, xrmi, ybmi, xlmi;
- double mapoint_i, mapoint;
-
- gint xcma_shift, ycma_shift;
- gint xcmi_shift, ycmi_shift;
- gint ytma_shift, ytmi_shift;
- gint xrma_shift, xrmi_shift;
- gint ybma_shift, ybmi_shift;
- gint xlma_shift, xlmi_shift;
-
- EdgeType *presentma;
- EdgeType *presentmi;
-
-
- if ((yt == yb) && (xr == xl) && (yt == xr))
- {
- /*Zero*/
-
- ytma = ytmi = xrma = xrmi = ybma = ybmi = xlma = xlmi = yt;
- ycma = ycmi = yc;
- xcma = xcmi = xc;
-
- }
- else if (xr == xl)
- {
- if (yt > yb)
- {
- /*South*/
-
- /*The Max circle*/
- ytma = ybma = xrma = xlma = xl;
- mapoint_i = (((yt * yt) / yb) - yt);
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc;
- ycma = yc + mapoint;
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = xl/2;
- xcmi = xc;
- ycmi = yc - mapoint/2;
-
- }
- else
- {
- /*North*/
-
- /*The Max circle*/
- ytma = ybma = xrma = xlma = xl;
- mapoint_i = (((yb * yb) / yt) - yb);
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc;
- ycma = yc - mapoint;
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = xl/2;
- xcmi = xc;
- ycmi = yc + mapoint/2;
-
- }
- }
- else if (yt == yb)
- {
- if (xr > xl)
- {
- /*East*/
-
- /*The Max circle*/
- ytma = ybma = xrma = xlma = yt;
- mapoint_i = (((xr * xr) /xl) -xr);
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = mapoint + xc;
- ycma = yc;
-
- /*The Min Circle*/
- ytmi = ybmi = xrmi = xlmi = yt/2;
- xcmi = xc - mapoint/2;
- ycmi = yc;
-
- }
- else
- {
- /*West*/
-
- /*The Max circle*/
- ytma = ybma = xrma = xlma = yt;
- mapoint_i = (((xl * xl) /xr) - xl);
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc - mapoint;
- ycma = yc;
-
-
- /*The Min Circle*/
- ytmi = ybmi = xrmi = xlmi = yt/2;
- xcmi = xc + mapoint/2;
- ycmi = yc;
-
- }
- }
- else if ((yt > yb) && (xr > xl))
- {
- /*SouthEast*/
-
- /*The Max circle*/
- ma_ang1 = atan(yt/xr);
- x1 = cos(ma_ang1) * xl;
- y1 = sin(ma_ang1) * yt;
- ma_ang2 = G_PI_2 - ma_ang1;
- x2 = cos(ma_ang2) * xr;
- y2 = sin(ma_ang2) * yb;
- xtotma = x1 + x2;
- ytotma = y1 + y2;
- ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
- mapoint_i = (((yt * yt + xr * xr) / hypot(yb, xl)) - hypot(yt, xr));
- mapoint = mapoint_i * pow(POWFAC , mapoint_i);
- xcma = xc + (cos(ma_ang1) * mapoint);
- ycma = yc + (sin(ma_ang1) * mapoint);
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = hypot(yb, xl)/2;
- xcmi = xc - (cos(ma_ang1) * mapoint * 0.5);
- ycmi = yc - (sin(ma_ang1) * mapoint * 0.5);
-
- }
- else if ((yt > yb) && (xl > xr))
- {
- /*SouthWest*/
-
- /*The Max circle*/
- ma_ang1 = atan(yt/xl);
- x1 = cos(ma_ang1) * xr;
- y1 = sin(ma_ang1) * yt;
- ma_ang2 = G_PI_2 - ma_ang1;
- x2 = cos(ma_ang2) * xl;
- y2 = sin(ma_ang2) * yb;
- xtotma = x1 + x2;
- ytotma = y1 + y2;
- ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
- mapoint_i = (((yt * yt + xl * xl) / hypot(yb, xr)) - hypot(yt, xl));
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc - (cos(ma_ang1) * mapoint);
- ycma = yc + (sin(ma_ang1) * mapoint);
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = hypot(yb, xr)/2;
- xcmi = xc + (cos(ma_ang1) * mapoint * 0.5);
- ycmi = yc - (sin(ma_ang1) * mapoint * 0.5);
-
- }
- else if ((yb > yt) && (xl > xr))
- {
- /*NorthWest*/
-
- /*The Max circle*/
- ma_ang1 = atan(yb/xl);
- x1 = cos(ma_ang1) * xl;
- y1 = sin(ma_ang1) * yt;
- ma_ang2 = G_PI_2 - ma_ang1;
- x2 = cos(ma_ang2) * xr;
- y2 = sin(ma_ang2) * yb;
- xtotma = x1 + x2;
- ytotma = y1 + y2;
- ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
- mapoint_i = (((yb * yb + xl * xl) / hypot(yt, xr)) - hypot(yb, xl));
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc - (cos(ma_ang1) * mapoint);
- ycma = yc - (sin(ma_ang1) * mapoint);
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = hypot(yt, xr)/2;
- xcmi = xc + (cos(ma_ang1) * mapoint * 0.5);
- ycmi = yc + (sin(ma_ang1) * mapoint * 0.5);
-
- }
- else
- /*if ((yb > yt) && (xr > xl))*/
- {
- /*NorthEast*/
-
- /*The Max circle*/
- ma_ang1 = atan(yb/xr);
- x1 = cos(ma_ang1) * xr;
- y1 = sin(ma_ang1) * yt;
- ma_ang2 = G_PI_2 - ma_ang1;
- x2 = cos(ma_ang2) * xl;
- y2 = sin(ma_ang2) * yb;
- xtotma = x1 + x2;
- ytotma = y1 + y2;
- ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
- mapoint_i = (((yb * yb + xr * xr) / hypot(yt, xl)) - hypot(yb, xr));
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc + (cos(ma_ang1) * mapoint);
- ycma = yc - (sin(ma_ang1) * mapoint);
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = hypot(yt, xl)/2;
- xcmi = xc - (cos(ma_ang1) * mapoint * 0.5);
- ycmi = yc + (sin(ma_ang1) * mapoint * 0.5);
-
- }
- if (ytmi <= 0)
- {
- ytmi = ybmi = xrmi = xlmi = 1;
- }
-
- if (ytma <= 0)
- {
- ytma = ybma = xrma = xlma = 1;
- }
-
- if (!trig_initialized)
- {
- trig_initialized = 1;
- for (i=0; i<256; i++)
- trig_table[i] = 0.5 + sin(i * (G_PI / 128.0)) * (1 << TABLE_SHIFT);
- }
-
-
- /*Make the Max circle*/
-
- maxyma = ceil (ycma + fabs (ytma));
- minyma = floor (ycma - fabs (ybma));
-
-
-
- rma = airbrush_blob_new (minyma, maxyma - minyma + 1);
-
-
- presentma = g_new0 (EdgeType, rma->height);
-
- max_radius = ytma;
-
- step = TABLE_SIZE;
-
- while (step > 1 && (TABLE_SIZE / step < 4*max_radius))
- step >>= 1;
-
- /* Fill in the edge points */
-
- xcma_shift = 0.5 + xcma * (1 << TOTAL_SHIFT);
- ycma_shift = 0.5 + ycma * (1 << TOTAL_SHIFT);
- ytma_shift = 0.5 + ytma * (1 << ELLIPSE_SHIFT);
- xrma_shift = 0.5 + xrma * (1 << ELLIPSE_SHIFT);
- ybma_shift = 0.5 + ybma * (1 << ELLIPSE_SHIFT);
- xlma_shift = 0.5 + xlma * (1 << ELLIPSE_SHIFT);
-
-
- for (i = 0 ; i < TABLE_SIZE ; i += step)
- {
-
- gint x, y, yi, dydi;
-
- gint s = trig_table[i];
- gint c = trig_table[(TABLE_SIZE + TABLE_SIZE/4 - i) % TABLE_SIZE];
-
- if (i < TABLE_QUARTER )
- {
- x = (xcma_shift + c * xrma_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- yi = (ycma_shift + s * ytma_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- y = yi - rma->y;
- dydi = 1;
-
- }
- else if ( i < (2 * TABLE_QUARTER) )
- {
- x = (xcma_shift + c * xlma_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- yi = (ycma_shift + s * ytma_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
-
- y = yi - rma->y;
-
- dydi = -1;
- }
- else if ( i < (3 * TABLE_QUARTER) )
- {
- x = (xcma_shift + c * xlma_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- yi = (ycma_shift + s * ybma_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- y = yi - rma->y;
- dydi = -1;
-
- }
- else
- {
- x = (xcma_shift + c * xrma_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- y = ((ycma_shift + s * ybma_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT) - rma->y;
-
- dydi = 1;
-
- }
-
-
-
-
- if (dydi <= 0) /* left edge */
- {
- if (presentma[y] & EDGE_LEFT)
- {
- rma->data[y].left = MIN (rma->data[y].left, x);
- }
- else
- {
- presentma[y] |= EDGE_LEFT;
- rma->data[y].left = x;
- }
- }
-
- if (dydi > 0) /* right edge */
- {
- if (presentma[y] & EDGE_RIGHT)
- {
- rma->data[y].right = MAX (rma->data[y].right, x);
- }
- else
- {
- presentma[y] |= EDGE_RIGHT;
- rma->data[y].right = x;
- }
- }
- }
-
- /* Now fill in missing points */
-
- airbrush_blob_fill (rma, presentma);
- g_free (presentma);
-
- /*Make the Min circle*/
-
-
- maxymi = ceil (ycmi + fabs (ytmi));
- minymi = floor (ycmi - fabs (ybmi));
-
-
- rmi = airbrush_blob_new (minymi, maxymi - minymi + 1);
-
-
- presentmi = g_new0 (EdgeType, rmi->height);
-
- max_radius = ytmi;
-
- step = TABLE_SIZE;
-
- while (step > 1 && (TABLE_SIZE / step < 4*max_radius))
- step >>= 1;
-
- /* Fill in the edge points */
-
- xcmi_shift = 0.5 + xcmi * (1 << TOTAL_SHIFT);
- ycmi_shift = 0.5 + ycmi * (1 << TOTAL_SHIFT);
- ytmi_shift = 0.5 + ytmi * (1 << ELLIPSE_SHIFT);
- xrmi_shift = 0.5 + xrmi * (1 << ELLIPSE_SHIFT);
- ybmi_shift = 0.5 + ybmi * (1 << ELLIPSE_SHIFT);
- xlmi_shift = 0.5 + xlmi * (1 << ELLIPSE_SHIFT);
-
-
-
- for (i = 0 ; i < TABLE_SIZE ; i += step)
- {
-
- gint x, y, yi, dydi;
-
- gint s = trig_table[i];
- gint c = trig_table[(TABLE_SIZE + TABLE_SIZE/4 - i) % TABLE_SIZE];
-
- if (i < TABLE_QUARTER )
- {
- x = (xcmi_shift + c * xrmi_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- yi = (ycmi_shift + s * ytmi_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- y = yi - rmi->y;
- dydi = 1;
-
- }
- else if ( i < (2 * TABLE_QUARTER) )
- {
- x = (xcmi_shift + c * xlmi_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- yi = (ycmi_shift + s * ytmi_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
-
- y = yi - rmi->y;
-
- dydi = -1;
- }
- else if ( i < (3 * TABLE_QUARTER) )
- {
- x = (xcmi_shift + c * xlmi_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- yi = (ycmi_shift + s * ybmi_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- y = yi - rmi->y;
- dydi = -1;
-
- }
- else
- {
- x = (xcmi_shift + c * xrmi_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
- y = ((ycmi_shift + s * ybmi_shift +
- (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT) - rmi->y;
-
- dydi = 1;
-
- }
-
-
-
-
- if (dydi <= 0) /* left edge */
- {
- if (presentmi[y] & EDGE_LEFT)
- {
- rmi->data[y].left = MIN (rmi->data[y].left, x);
- }
- else
- {
- presentmi[y] |= EDGE_LEFT;
- rmi->data[y].left = x;
- }
- }
-
- if (dydi > 0) /* right edge */
- {
- if (presentmi[y] & EDGE_RIGHT)
- {
- rmi->data[y].right = MAX (rmi->data[y].right, x);
- }
- else
- {
- presentmi[y] |= EDGE_RIGHT;
- rmi->data[y].right = x;
- }
- }
- }
-
- /* Now fill in missing points */
-
- airbrush_blob_fill (rmi, presentmi);
- g_free (presentmi);
-
- rtot = airbrush_blob_convex_union(rma, rmi);
-
- g_free (rma);
- g_free (rmi);
-
- return rtot;
- }
-
- void
- airbrush_blob_bounds(AirBrushBlob *b, int *x, int *y, int *width, int *height)
- {
- int i;
- int x0, x1, y0, y1;
-
- i = 0;
- while (i<b->height && b->data[i].left > b->data[i].right)
- i++;
-
- if (i<b->height)
- {
- y0 = b->y + i;
- x0 = b->data[i].left;
- x1 = b->data[i].right + 1;
- while (i<b->height && b->data[i].left <= b->data[i].right)
- {
- x0 = MIN(b->data[i].left, x0);
- x1 = MAX(b->data[i].right+1, x1);
- i++;
- }
- y1 = b->y + i;
- }
- else
- {
- x0 = y0 = 0;
- x1 = y1 = 0;
- }
-
- *x = x0;
- *y = y0;
- *width = x1 - x0;
- *height = y1 - y0;
- }
-
- void
- airbrush_blob_dump(AirBrushBlob *b) {
-
- int i,j;
-
-
- for (i=0; i<b->height; i++)
- {
- for (j=0;j<b->data[i].left;j++)
- putchar(' ');
- for (j=b->data[i].left;j<=b->data[i].right;j++)
- putchar('*');
- putchar('\n');
- }
- }
-
- /* This is just a first try to see how it works i.e ugly code :-) */
-
-
- AirBlob *
- create_air_blob (double xc,
- double yc,
- double xt,
- double yt,
- double xr,
- double yr,
- double xb,
- double yb,
- double xl,
- double yl,
- double direction_abs,
- double direction)
- {
- AirBlob *air_blob;
- double ma_ang1, ma_ang2;
- double x1, x2, y1, y2;
- double xtotma, ytotma;
- double xcma, ycma, ytma, xrma, ybma, xlma;
- double xcmi, ycmi, ytmi, xrmi, ybmi, xlmi;
- double mapoint_i, mapoint;
-
- air_blob = airblob_new(1);
-
- air_blob->direction_abs = direction_abs;
- air_blob->direction = direction;
- air_blob->ycenter = yc;
- air_blob->xcenter = xc;
-
- if ((yt == yb) && (xr == xl) && (yt == xr))
- {
- /*Zero*/
-
- ytma = ytmi = xrma = xrmi = ybma = ybmi = xlma = xlmi = yt;
- ycma = ycmi = yc;
- xcma = xcmi = xc;
-
- air_blob->main_line.size = yt;
- air_blob->minor_line.size = yt;
-
- air_blob->maincross_line.size = yt * 2;
- air_blob->maincross_line.dist = 0.0;
-
- air_blob->minorcross_line.size = yt * 2;
- air_blob->minorcross_line.dist = 0.0;
-
- air_blob->direction = G_PI_2;
-
- }
- else if (xr == xl)
- {
- if (yt > yb)
- {
- /*South*/
-
- /*The Max circle*/
- ytma = ybma = xrma = xlma = xl;
- mapoint_i = (((yt * yt) / yb) - yt);
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc;
- ycma = yc + mapoint;
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = xl/2;
- xcmi = xc;
- ycmi = yc - mapoint/2;
-
- air_blob->main_line.size = mapoint + xl;
- air_blob->minor_line.size = mapoint/2 + xl/2;
-
- air_blob->maincross_line.size = xl * 2;
- air_blob->maincross_line.dist = mapoint;
-
- air_blob->minorcross_line.size = xl/2;
- air_blob->minorcross_line.dist = mapoint/2;
-
-
-
- }
- else
- {
- /*North*/
-
- /*The Max circle*/
- ytma = ybma = xrma = xlma = xl;
- mapoint_i = (((yb * yb) / yt) - yb);
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc;
- ycma = yc - mapoint;
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = xl/2;
- xcmi = xc;
- ycmi = yc + mapoint/2;
-
-
- air_blob->main_line.size = mapoint + xl;
- air_blob->minor_line.size = mapoint/2 + xl/2;
-
- air_blob->maincross_line.size = xl * 2;
- air_blob->maincross_line.dist = mapoint;
-
- air_blob->minorcross_line.size = xl/2;
- air_blob->minorcross_line.dist = mapoint/2;
-
-
- }
- }
- else if (yt == yb)
- {
- if (xr > xl)
- {
- /*East*/
-
- /*The Max circle*/
- ytma = ybma = xrma = xlma = yt;
- mapoint_i = (((xr * xr) /xl) -xr);
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = mapoint + xc;
- ycma = yc;
-
- /*The Min Circle*/
- ytmi = ybmi = xrmi = xlmi = yt/2;
- xcmi = xc - mapoint/2;
- ycmi = yc;
-
- air_blob->main_line.size = mapoint + yt;
- air_blob->minor_line.size = mapoint/2 + yt/2;
-
- air_blob->maincross_line.size = xl * 2;
- air_blob->maincross_line.dist = mapoint;
-
- air_blob->minorcross_line.size = xl/2;
- air_blob->minorcross_line.dist = mapoint/2;
-
-
- }
- else
- {
- /*West*/
-
- /*The Max circle*/
- ytma = ybma = xrma = xlma = yt;
- mapoint_i = (((xl * xl) /xr) - xl);
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc - mapoint;
- ycma = yc;
-
-
- /*The Min Circle*/
- ytmi = ybmi = xrmi = xlmi = yt/2;
- xcmi = xc + mapoint/2;
- ycmi = yc;
-
- air_blob->main_line.size = mapoint + yt;
- air_blob->minor_line.size = mapoint/2 + yt/2;
-
- air_blob->maincross_line.size = xl * 2;
- air_blob->maincross_line.dist = mapoint;
-
- air_blob->minorcross_line.size = xl/2;
- air_blob->minorcross_line.dist = mapoint/2;
-
-
- }
- }
- else if ((yt > yb) && (xr > xl))
- {
- /*SouthEast*/
-
- /*The Max circle*/
- ma_ang1 = atan(yt/xr);
- x1 = cos(ma_ang1) * xl;
- y1 = sin(ma_ang1) * yt;
- ma_ang2 = G_PI_2 - ma_ang1;
- x2 = cos(ma_ang2) * xr;
- y2 = sin(ma_ang2) * yb;
- xtotma = x1 + x2;
- ytotma = y1 + y2;
- ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
- mapoint_i = (((yt * yt + xr * xr) / hypot(yb, xl)) - hypot(yt, xr));
- mapoint = mapoint_i * pow(POWFAC , mapoint_i);
- xcma = xc + (cos(ma_ang1) * mapoint);
- ycma = yc + (sin(ma_ang1) * mapoint);
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = hypot(yb, xl)/2;
- xcmi = xc - (cos(ma_ang1) * mapoint * 0.5);
- ycmi = yc - (sin(ma_ang1) * mapoint * 0.5);
-
-
- air_blob->main_line.size = mapoint + xlma;
- air_blob->minor_line.size = mapoint/2 + xlmi;
-
-
- air_blob->maincross_line.size = xlma * 2;
- air_blob->maincross_line.dist = mapoint;
-
- air_blob->minorcross_line.size = xlmi;
- air_blob->minorcross_line.dist = mapoint/2;
-
-
-
-
- }
- else if ((yt > yb) && (xl > xr))
- {
- /*SouthWest*/
-
- /*The Max circle*/
- ma_ang1 = atan(yt/xl);
- x1 = cos(ma_ang1) * xr;
- y1 = sin(ma_ang1) * yt;
- ma_ang2 = G_PI_2 - ma_ang1;
- x2 = cos(ma_ang2) * xl;
- y2 = sin(ma_ang2) * yb;
- xtotma = x1 + x2;
- ytotma = y1 + y2;
- ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
- mapoint_i = (((yt * yt + xl * xl) / hypot(yb, xr)) - hypot(yt, xl));
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc - (cos(ma_ang1) * mapoint);
- ycma = yc + (sin(ma_ang1) * mapoint);
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = hypot(yb, xr)/2;
- xcmi = xc + (cos(ma_ang1) * mapoint * 0.5);
- ycmi = yc - (sin(ma_ang1) * mapoint * 0.5);
-
- air_blob->main_line.size = mapoint + xlma;
- air_blob->minor_line.size = mapoint/2 + xlmi;
-
- air_blob->maincross_line.size = xlma * 2;
- air_blob->maincross_line.dist = mapoint;
-
- air_blob->minorcross_line.size = xlmi;
- air_blob->minorcross_line.dist = mapoint/2;
-
- }
- else if ((yb > yt) && (xl > xr))
- {
- /*NorthWest*/
-
- /*The Max circle*/
- ma_ang1 = atan(yb/xl);
- x1 = cos(ma_ang1) * xl;
- y1 = sin(ma_ang1) * yt;
- ma_ang2 = G_PI_2 - ma_ang1;
- x2 = cos(ma_ang2) * xr;
- y2 = sin(ma_ang2) * yb;
- xtotma = x1 + x2;
- ytotma = y1 + y2;
- ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
- mapoint_i = (((yb * yb + xl * xl) / hypot(yt, xr)) - hypot(yb, xl));
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc - (cos(ma_ang1) * mapoint);
- ycma = yc - (sin(ma_ang1) * mapoint);
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = hypot(yt, xr)/2;
- xcmi = xc + (cos(ma_ang1) * mapoint * 0.5);
- ycmi = yc + (sin(ma_ang1) * mapoint * 0.5);
-
- air_blob->main_line.size = mapoint + xlma;
- air_blob->minor_line.size = mapoint/2 + xlmi;
-
- air_blob->maincross_line.size = xlma * 2;
- air_blob->maincross_line.dist = mapoint;
-
- air_blob->minorcross_line.size = xlmi;
- air_blob->minorcross_line.dist = mapoint/2;
-
-
-
-
- }
- else
- /*if ((yb > yt) && (xr > xl))*/
- {
- /*NorthEast*/
-
- /*The Max circle*/
- ma_ang1 = atan(yb/xr);
- x1 = cos(ma_ang1) * xr;
- y1 = sin(ma_ang1) * yt;
- ma_ang2 = G_PI_2 - ma_ang1;
- x2 = cos(ma_ang2) * xl;
- y2 = sin(ma_ang2) * yb;
- xtotma = x1 + x2;
- ytotma = y1 + y2;
- ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
- mapoint_i = (((yb * yb + xr * xr) / hypot(yt, xl)) - hypot(yb, xr));
- mapoint = mapoint_i * pow(POWFAC, mapoint_i);
- xcma = xc + (cos(ma_ang1) * mapoint);
- ycma = yc - (sin(ma_ang1) * mapoint);
-
- /*The Min Circle*/
- ytmi = xrmi = ybmi = xlmi = hypot(yt, xl)/2;
- xcmi = xc - (cos(ma_ang1) * mapoint * 0.5);
- ycmi = yc + (sin(ma_ang1) * mapoint * 0.5);
-
- air_blob->main_line.size = mapoint + xlma;
- air_blob->minor_line.size = mapoint/2 + xlmi;
-
-
- air_blob->maincross_line.size = xlma * 2;
- air_blob->maincross_line.dist = mapoint;
-
- air_blob->minorcross_line.size = xlmi;
- air_blob->minorcross_line.dist = mapoint/2;
-
-
- }
-
- return air_blob;
- }
-
- AirLine *
- create_air_line(AirBlob *airblob)
- {
-
- int i;
- double xcenter, ycenter;
-
- double direction;
-
- double masupport, misupport;
- double ma_angsupport, mi_angsupport, iang;
-
- int min_x, max_x;
- int min_y, max_y;
-
- AirLine *airline;
-
- /*
- Yes I know I can do a cal of number of lines, but it is for
- the moment much easier to just set a side mem for 16 lines
- */
-
- airline = airline_new(1);
-
- xcenter = airblob->xcenter;
- ycenter = airblob->ycenter;
-
- airline->xcenter = xcenter/SUBSAMPLE;
- airline->ycenter = ycenter/SUBSAMPLE;
-
- direction = airblob->direction_abs;
-
- /*
- printf("Direction: %f\n", direction);
- printf("Xcenter: %f\n",xcenter/SUBSAMPLE);
- printf("Ycenter: %f\n",ycenter/SUBSAMPLE);
- printf("MaCr.dist: %f\n",airblob->maincross_line.dist);
- printf("MaCr.size: %f\n",airblob->maincross_line.size);
- printf("MiCr.dist: %f\n",airblob->minorcross_line.dist);
- printf("MiCr.size: %f\n",airblob->minorcross_line.size);
- printf("Ma.size: %f\n",airblob->main_line.size);
- printf("Mi.size: %f\n",airblob->minor_line.size);
- */
-
- if (direction == G_PI_2 || direction == G_PI)
- {
- direction = direction - 0.001;
- }
-
- if (direction == -G_PI_2 || direction == -G_PI)
- {
- direction = direction + 0.001;
- }
-
- if(direction == 0.0)
-
- {
-
- airline->line[0].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[0].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[1].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[1].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->line[2].x = (xcenter + airblob->main_line.size)/SUBSAMPLE;
- airline->line[2].y = (ycenter)/SUBSAMPLE;
- airline->line[3].x = (xcenter - airblob->minor_line.size)/SUBSAMPLE;
- airline->line[3].y = (ycenter)/SUBSAMPLE;
-
- airline->line[4].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[4].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[5].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[5].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->nlines = 6;
-
-
- }
-
- else if(direction == G_PI_2)
-
- {
-
- airline->line[0].x = (xcenter - airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[0].y = (ycenter - airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[1].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->line[2].x = (xcenter)/SUBSAMPLE;
- airline->line[2].y = (ycenter - airblob->main_line.size)/SUBSAMPLE;
- airline->line[3].x = (xcenter)/SUBSAMPLE;
- airline->line[3].y = (ycenter + airblob->minor_line.size)/SUBSAMPLE;
-
- airline->line[4].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[4].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[5].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[5].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->nlines = 6;
- printf("Hmm bummer G_PI_2\n");
-
- }
-
-
- else if(direction == G_PI)
-
- {
- airline->line[0].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[0].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[1].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->line[2].x = (xcenter - airblob->main_line.size)/SUBSAMPLE;
- airline->line[2].y = (ycenter)/SUBSAMPLE;
- airline->line[3].x = (xcenter + airblob->minor_line.size)/SUBSAMPLE;
- airline->line[3].y = (ycenter)/SUBSAMPLE;
-
- airline->line[4].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[4].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[5].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[5].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->nlines = 6;
-
- printf("Hmm bummer G_PI\n");
-
-
- }
-
- else if(direction == -G_PI_2)
-
- {
- airline->line[0].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[0].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[1].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->line[2].x = (xcenter)/SUBSAMPLE;
- airline->line[2].y = (ycenter + airblob->main_line.size)/SUBSAMPLE;
- airline->line[3].x = (xcenter)/SUBSAMPLE;
- airline->line[3].y = (ycenter - airblob->minor_line.size)/SUBSAMPLE;
-
- airline->line[4].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[4].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[5].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[5].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->nlines = 6;
-
- printf("Hmm bummer -G_PI_2\n");
-
-
-
- }
-
-
- else if(direction == -G_PI)
-
- {
- airline->line[0].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[0].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[1].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->line[2].x = (xcenter - airblob->main_line.size)/SUBSAMPLE;
- airline->line[2].y = (ycenter)/SUBSAMPLE;
- airline->line[3].x = (xcenter + airblob->minor_line.size)/SUBSAMPLE;
- airline->line[3].y = (ycenter)/SUBSAMPLE;
-
- airline->line[4].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
- airline->line[4].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE;
- airline->line[5].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
- airline->line[5].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
-
- airline->nlines = 6;
-
- printf("Hmm bummer -G_PI\n");
-
-
- }
-
-
- else if ((direction < G_PI) && (direction > G_PI_2))
-
- {
-
-
- masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2);
- misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2);
-
- ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist);
- mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist);
-
- iang = airblob->direction_abs - G_PI_2;
-
- airline->line[0].x = (xcenter - sin(iang + ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[0].y = (ycenter - cos(iang + ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[1].x = (xcenter + sin(iang + mi_angsupport) * misupport)/SUBSAMPLE;
- airline->line[1].y = (ycenter + cos(iang + mi_angsupport) * misupport)/SUBSAMPLE;
-
- airline->line[2].x = (xcenter - sin(iang) * airblob->main_line.size)/SUBSAMPLE;
- airline->line[2].y = (ycenter - cos(iang) * airblob->main_line.size)/SUBSAMPLE;
- airline->line[3].x = (xcenter + sin(iang) * airblob->minor_line.size)/SUBSAMPLE;
- airline->line[3].y = (ycenter + cos(iang) * airblob->minor_line.size)/SUBSAMPLE;
-
- airline->line[4].x = (xcenter - sin(iang - ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[4].y = (ycenter - cos(iang - ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[5].x = (xcenter + sin(iang - mi_angsupport) * misupport)/SUBSAMPLE;
- airline->line[5].y = (ycenter + cos(iang - mi_angsupport) * misupport)/SUBSAMPLE;
-
- /*airline->line[6].x = (xcenter - sin(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[6].y = (ycenter - cos(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[7].x = (xcenter - sin(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[7].y = (ycenter - cos(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
-
- airline->line[8].x = (xcenter - sin(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[8].y = (ycenter - cos(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[9].x = (xcenter - sin(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[9].y = (ycenter - cos(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
-
- airline->line[10].x = (xcenter - sin(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[10].y = (ycenter - cos(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[11].x = (xcenter - sin(iang - ma_angsupport/2. - ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[11].y = (ycenter - cos(iang - ma_angsupport/2. - ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;*/
-
-
- airline->nlines = 6;
-
- }
-
- else if ((direction < G_PI_2) && (direction > 0.0))
-
- {
-
-
- masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2);
- misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2);
-
- ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist);
- mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist);
-
- iang = airblob->direction_abs;
-
- airline->line[0].x = (xcenter + cos(iang + ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[0].y = (ycenter - sin(iang + ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[1].x = (xcenter - cos(iang + mi_angsupport) * misupport)/SUBSAMPLE;
- airline->line[1].y = (ycenter + sin(iang + mi_angsupport) * misupport)/SUBSAMPLE;
-
- airline->line[2].x = (xcenter + cos(iang) * airblob->main_line.size)/SUBSAMPLE;
- airline->line[2].y = (ycenter - sin(iang) * airblob->main_line.size)/SUBSAMPLE;
- airline->line[3].x = (xcenter - cos(iang) * airblob->minor_line.size)/SUBSAMPLE;
- airline->line[3].y = (ycenter + sin(iang) * airblob->minor_line.size)/SUBSAMPLE;
-
- airline->line[4].x = (xcenter + cos(iang - ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[4].y = (ycenter - sin(iang - ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[5].x = (xcenter - cos(iang - mi_angsupport) * misupport)/SUBSAMPLE;
- airline->line[5].y = (ycenter + sin(iang - mi_angsupport) * misupport)/SUBSAMPLE;
-
-
- /*airline->line[6].x = (xcenter + cos(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[6].y = (ycenter - sin(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[7].x = (xcenter + cos(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[7].y = (ycenter - sin(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
-
- airline->line[8].x = (xcenter + cos(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[8].y = (ycenter - sin(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[9].x = (xcenter + cos(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[9].y = (ycenter - sin(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
-
- airline->line[10].x = (xcenter + cos(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[10].y = (ycenter - sin(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[11].x = (xcenter + cos(iang - ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
- airline->line[11].y = (ycenter - sin(iang - ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
-
- airline->line[12].x = airline->line[2].x + (airline->line[4].x - airline->line[2].x)/4;
- airline->line[12].y = airline->line[2].y + (airline->line[4].y - airline->line[2].y)/4;
- airline->line[13].x = airline->line[2].x + 3 * (airline->line[4].x - airline->line[2].x)/4;
- airline->line[13].y = airline->line[2].y + 3 * (airline->line[4].y - airline->line[2].y)/4;
- */
-
-
-
- airline->nlines = 6;
-
-
- }
-
-
- else if ((direction < 0.0) && (direction > -G_PI_2))
-
- {
-
-
- masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2);
- misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2);
-
- ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist);
- mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist);
-
- iang = fabs(airblob->direction_abs);
-
- airline->line[0].x = (xcenter + cos(iang + ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[0].y = (ycenter + sin(iang + ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[1].x = (xcenter - cos(iang + mi_angsupport) * misupport)/SUBSAMPLE;
- airline->line[1].y = (ycenter - sin(iang + mi_angsupport) * misupport)/SUBSAMPLE;
-
- airline->line[2].x = (xcenter + cos(iang) * airblob->main_line.size)/SUBSAMPLE;
- airline->line[2].y = (ycenter + sin(iang) * airblob->main_line.size)/SUBSAMPLE;
- airline->line[3].x = (xcenter - cos(iang) * airblob->minor_line.size)/SUBSAMPLE;
- airline->line[3].y = (ycenter - sin(iang) * airblob->minor_line.size)/SUBSAMPLE;
-
- airline->line[4].x = (xcenter + cos(iang - ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[4].y = (ycenter + sin(iang - ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[5].x = (xcenter - cos(iang - mi_angsupport) * misupport)/SUBSAMPLE;
- airline->line[5].y = (ycenter - sin(iang - mi_angsupport) * misupport)/SUBSAMPLE;
-
- airline->nlines = 6;
-
- }
-
-
- else if ((direction < -G_PI_2) && (direction > -G_PI))
-
- {
-
-
- masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2);
- misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2);
-
- ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist);
- mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist);
-
- iang = fabs(airblob->direction_abs) - G_PI_2;
-
- airline->line[0].x = (xcenter - sin(iang + ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[0].y = (ycenter + cos(iang + ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[1].x = (xcenter + sin(iang + mi_angsupport) * misupport)/SUBSAMPLE;
- airline->line[1].y = (ycenter - cos(iang + mi_angsupport) * misupport)/SUBSAMPLE;
-
- airline->line[2].x = (xcenter - sin(iang) * airblob->main_line.size)/SUBSAMPLE;
- airline->line[2].y = (ycenter + cos(iang) * airblob->main_line.size)/SUBSAMPLE;
- airline->line[3].x = (xcenter + sin(iang) * airblob->minor_line.size)/SUBSAMPLE;
- airline->line[3].y = (ycenter - cos(iang) * airblob->minor_line.size)/SUBSAMPLE;
-
- airline->line[4].x = (xcenter - sin(iang - ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[4].y = (ycenter + cos(iang - ma_angsupport) * masupport)/SUBSAMPLE;
- airline->line[5].x = (xcenter + sin(iang - mi_angsupport) * misupport)/SUBSAMPLE;
- airline->line[5].y = (ycenter - cos(iang - mi_angsupport) * misupport)/SUBSAMPLE;
-
- airline->nlines = 6;
-
- }
- else
- {
- printf("Hmm a bug in the create_air_line");
- }
-
-
-
-
-
- min_x = max_x = airline->xcenter;
- min_y = max_y = airline->ycenter;
-
- /*
-
- for (i=0; i < airline->nlines ; i++)
- {
- printf("x%d, value %d\n", i, airline->line[i].x);
- printf("y%d, value %d\n", i, airline->line[i].y);
- }
-
- printf("The xcenter %d\n",airline->xcenter);
- printf("The ycenter %d\n",airline->ycenter);
-
- */
-
- for (i=0; i < airline->nlines ; i++)
- {
- min_x = MIN(airline->line[i].x, min_x);
- max_x = MAX(airline->line[i].x, max_x);
- min_y = MIN(airline->line[i].y, min_y);
- max_y = MAX(airline->line[i].y, max_y);
- }
-
- airline->width = max_x - min_x + 1;
- airline->height = max_y - min_y + 1;
-
- airline->min_x = min_x;
- airline->min_y = min_y;
- airline->max_x = max_x;
- airline->max_y = max_y;
-
- return airline;
-
- }
-
- AirBlob *
- trans_air_blob(AirBlob *airblob_last, AirBlob *airblob_present, double dist, int xcen, int ycen)
- {
-
- AirBlob *trans_airblob;
-
- double direction_last_abs, direction_present_abs;
- double idirection_abs;
-
- double direction_last, direction_present;
- double idirection;
-
- double main_line_present, main_line_last;
-
-
- double minor_line_present, minor_line_last;
-
-
- double maincross_line_dist_present, maincross_line_dist_last;
-
- double minorcross_line_dist_present, minorcross_line_dist_last;
-
-
- double maincross_line_size_present, maincross_line_size_last;
-
- double minorcross_line_size_present, minorcross_line_size_last;
-
-
-
- trans_airblob = airblob_new(1);
-
- direction_last_abs = airblob_last->direction_abs + G_PI;
- direction_present_abs = airblob_present->direction_abs + G_PI;
-
- idirection_abs = direction_present_abs - direction_last_abs;
-
- direction_last = airblob_last->direction + G_PI_2;
- direction_present = airblob_present->direction + G_PI_2;
-
- idirection = direction_present - direction_last;
-
- main_line_present = airblob_present->main_line.size;
- main_line_last = airblob_last->main_line.size;
-
- minor_line_present = airblob_present->minor_line.size;
- minor_line_last = airblob_last->minor_line.size;
-
- maincross_line_dist_present = airblob_present->maincross_line.dist;
- maincross_line_size_present = airblob_present->maincross_line.size;
- minorcross_line_dist_present = airblob_present->minorcross_line.dist;
- minorcross_line_size_present = airblob_present->minorcross_line.size;
-
- maincross_line_dist_last = airblob_last->maincross_line.dist;
- maincross_line_size_last = airblob_last->maincross_line.size;
- minorcross_line_dist_last = airblob_last->minorcross_line.dist;
- minorcross_line_size_last = airblob_last->minorcross_line.size;
-
-
-
-
- /*
- Now we have to guess a little :-). Why?
- Well we can't know if the users is painting
- up/down or if she is painting a circle at high speed.
- As you may notice it be so that the last airblob has
- a direction more or less G_PI rad differernt from the
- present airblob. But we can't know if she tured the
- airbrush quickly (so that there was no mouse capture
- during the turn) or if she paints just up and down the
- same direction.
-
- There for we guess that we want to pait up and down
- when the diff in direction is bigger than 171 deg and
- smaller than 189 deg.
-
- */
-
- if ((fabs(idirection_abs) > (G_PI - 0.1571)) && (fabs(idirection_abs) < (G_PI + 0.1571)))
- {
- /* We asume that the artist meant to paint in a "strait line" by just tilting the airbrush*/
-
- idirection_abs = idirection_abs - G_PI;
-
- if ((idirection_abs * dist) > (idirection_abs/2))
- {
- if ((direction_present_abs - idirection_abs * dist) > 2 * G_PI)
- {
- trans_airblob->direction_abs = direction_present_abs - idirection_abs * dist - 2 * G_PI - G_PI;
- }
- else if ((direction_present_abs - idirection_abs * dist) < 0.0)
- {
- trans_airblob->direction_abs = direction_present_abs - idirection_abs * dist + 2 * G_PI - G_PI;
- }
- else
- {
- trans_airblob->direction_abs = direction_present_abs - idirection_abs * dist - G_PI;
- }
- }
- else
- {
- if ((direction_present_abs + idirection_abs * dist) > 2 * G_PI)
- {
- trans_airblob->direction_abs = direction_present_abs + idirection_abs * dist - 2 * G_PI - G_PI;
- }
- else if ((direction_present_abs + idirection_abs * dist) < 0.0)
- {
- trans_airblob->direction_abs = direction_present_abs + idirection_abs * dist + 2 * G_PI - G_PI;
- }
- else
- {
- trans_airblob->direction_abs = direction_present_abs + idirection_abs * dist - G_PI;
- }
- }
-
- trans_airblob->main_line.size = main_line_last + ((minor_line_present - main_line_last) * dist);
- trans_airblob->minor_line.size = minor_line_last + ((main_line_present - minor_line_last) * dist);
-
- trans_airblob->maincross_line.dist = maincross_line_dist_last + ((minorcross_line_dist_present - maincross_line_dist_last) * dist);
- trans_airblob->maincross_line.size = maincross_line_size_last + ((minorcross_line_size_present - maincross_line_size_last) * dist);
-
- trans_airblob->minorcross_line.dist = minorcross_line_dist_last + ((maincross_line_dist_present - minorcross_line_dist_last) * dist);
- trans_airblob->minorcross_line.size = minorcross_line_size_last + ((maincross_line_size_present - minorcross_line_size_last) * dist);
-
- }
-
- else if (fabs(idirection_abs) < (G_PI - 0.1571))
- {
- if ((direction_last_abs + idirection_abs * dist) > 2*G_PI)
- {
- trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - 2 * G_PI - G_PI;
- }
- else if((direction_last_abs + idirection_abs * dist) < 0.0)
- {
- trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist + 2 * G_PI - G_PI;
- }
- else
- {
- trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - G_PI;
- }
-
- trans_airblob->main_line.size = main_line_last + ((main_line_present - main_line_last) * dist);
- trans_airblob->minor_line.size = minor_line_last + ((minor_line_present - minor_line_last) * dist);
-
- trans_airblob->maincross_line.dist = maincross_line_dist_last + ((maincross_line_dist_present - maincross_line_dist_last) * dist);
- trans_airblob->maincross_line.size = maincross_line_size_last + ((maincross_line_size_present - maincross_line_size_last) * dist);
-
- trans_airblob->minorcross_line.dist = minorcross_line_dist_last + ((minorcross_line_dist_present - minorcross_line_dist_last) * dist);
- trans_airblob->minorcross_line.size = minorcross_line_size_last + ((minorcross_line_size_present - minorcross_line_size_last) * dist);
- }
- else
- {
-
- /* We asume that the artist always travels the shortest way around the "clock" */
-
- idirection_abs = idirection_abs - G_PI;
-
- if ((direction_last_abs + idirection_abs * dist) > 2*G_PI)
- {
- trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - 2 * G_PI - G_PI;
- }
- else if((direction_last_abs + idirection_abs * dist) < 0.0)
- {
- trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist + 2 * G_PI - G_PI;
- }
- else
- {
- trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - G_PI;
- }
-
- trans_airblob->main_line.size = main_line_last + ((main_line_present - main_line_last) * dist);
- trans_airblob->minor_line.size = minor_line_last + ((minor_line_present - minor_line_last) * dist);
-
- trans_airblob->maincross_line.dist = maincross_line_dist_last + ((maincross_line_dist_present - maincross_line_dist_last) * dist);
- trans_airblob->maincross_line.size = maincross_line_size_last + ((maincross_line_size_present - maincross_line_size_last) * dist);
-
- trans_airblob->minorcross_line.dist = minorcross_line_dist_last + ((minorcross_line_dist_present - minorcross_line_dist_last) * dist);
- trans_airblob->minorcross_line.size = minorcross_line_size_last + ((minorcross_line_size_present - minorcross_line_size_last) * dist);
-
- }
-
-
- trans_airblob->xcenter = xcen * SUBSAMPLE;
- trans_airblob->ycenter = ycen * SUBSAMPLE;
-
- return trans_airblob;
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-