home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / airbrush_blob.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-07  |  53.5 KB  |  1,842 lines

  1. /* airbrush_blob.c: routines for manipulating scan converted convex
  2.  *         polygons.
  3.  *  
  4.  * Copyright 1998-1999, Owen Taylor <otaylor@gtk.org>
  5.  *
  6.  * > Please contact the above author before modifying the copy <
  7.  * > of this file in the GIMP distribution. Thanks.            <
  8.  * 
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. */
  23.  
  24. #include <glib.h>
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29.  
  30. #include <libgimp/gimpmath.h>
  31.  
  32. #include "airbrush_blob.h"
  33.  
  34.  
  35. #define SUBSAMPLE 8.0
  36. #define SU 8.0
  37.  
  38.  
  39. static AirBrushBlob *
  40. airbrush_blob_new (int y, int height)
  41. {
  42.   
  43.   AirBrushBlob *result;
  44.  
  45.   result = g_malloc (sizeof (AirBrushBlob) +  sizeof(AirBrushBlobSpan) * (height-1));
  46.   result->y = y;
  47.   result->height = height;
  48.   return result;
  49. }
  50.  
  51.  
  52. static AirBlob *
  53. airblob_new(int y) 
  54. {
  55.   AirBlob  *result;
  56.   
  57.   result = g_malloc (sizeof (AirBlob));
  58.   return result;
  59. }
  60.  
  61. static AirLine *
  62. airline_new(int y)
  63. {
  64.   AirLine *result;
  65.  
  66.   result = g_malloc(sizeof (AirLine));
  67.   return result;
  68. }
  69.  
  70.  
  71.  
  72.  
  73.  
  74. typedef enum {
  75.   EDGE_NONE = 0,
  76.   EDGE_LEFT = 1 << 0,
  77.   EDGE_RIGHT = 1 << 1
  78. } EdgeType;
  79.  
  80. static void
  81. airbrush_blob_fill (AirBrushBlob *b, EdgeType *present)
  82. {
  83.  
  84.   int start;
  85.   int x1, x2, i1, i2;
  86.   int i;
  87.  
  88.   /* Mark empty lines at top and bottom as unused */
  89.  
  90.   start = 0;
  91.   while (!(present[start])) 
  92.     {
  93.       b->data[start].left = 0;
  94.       b->data[start].right = -1;
  95.       start++;
  96.     }
  97.   if (present[start] != (EDGE_RIGHT | EDGE_LEFT))
  98.     {
  99.       if (present[start] == EDGE_RIGHT)
  100.     b->data[start].left = b->data[start].right;
  101.       else
  102.     b->data[start].right = b->data[start].left;
  103.     
  104.       present[start] = EDGE_RIGHT | EDGE_LEFT;
  105.     }
  106.  
  107.   for (i=b->height-1;!present[i];i--)
  108.     {
  109.       b->data[i].left = 0;
  110.       b->data[i].right = -1;
  111.     }
  112.   if (present[i] != (EDGE_RIGHT | EDGE_LEFT))
  113.     {
  114.       if (present[i] == EDGE_RIGHT)
  115.     b->data[i].left = b->data[i].right;
  116.       else
  117.     b->data[i].right = b->data[i].left;
  118.     
  119.       present[i] = EDGE_RIGHT | EDGE_LEFT;
  120.     }
  121.  
  122.  
  123.   /* Restore missing edges  */
  124.  
  125.   /* We fill only interior regions of convex hull, as if we were filling
  126.      polygons. But since we draw ellipses with nearest points, not interior
  127.      points, maybe it would look better if we did the same here. Probably
  128.      not a big deal either way after anti-aliasing */
  129.  
  130.   /*     left edge */
  131.   for (i1=start; i1<b->height-2; i1++)
  132.     {
  133.       /* Find empty gaps */
  134.       if (!(present[i1+1] & EDGE_LEFT))
  135.     {
  136.       int increment;    /* fractional part */
  137.       int denom;        /* denominator of fraction */
  138.       int step;        /* integral step */
  139.       int frac;        /* fractional step */
  140.       int reverse;
  141.  
  142.       /* find bottom of gap */
  143.       i2 = i1+2;
  144.       while (!(present[i2] & EDGE_LEFT) && i2 < b->height) i2++;
  145.       
  146.       if (i2 < b->height)
  147.         {
  148.           denom = i2-i1;
  149.           x1 = b->data[i1].left;
  150.           x2 = b->data[i2].left;
  151.           step = (x2-x1)/denom;
  152.           frac = x2-x1 - step*denom;
  153.           if (frac < 0)
  154.         {
  155.           frac = -frac;
  156.           reverse = 1;
  157.         }
  158.           else
  159.         reverse = 0;
  160.           
  161.           increment = 0;
  162.           for (i=i1+1; i<i2; i++)
  163.         {
  164.           x1 += step;
  165.           increment += frac;
  166.           if (increment >= denom)
  167.             {
  168.               increment -= denom;
  169.               x1 += reverse ? -1 : 1;
  170.             }
  171.           if (increment == 0 || reverse)
  172.             b->data[i].left = x1;
  173.           else
  174.             b->data[i].left = x1 + 1;
  175.         }
  176.         }
  177.       i1 = i2-1;        /* advance to next possibility */
  178.     }
  179.     }
  180.  
  181.   /*     right edge */
  182.   for (i1=start; i1<b->height-2; i1++)
  183.     {
  184.       /* Find empty gaps */
  185.       if (!(present[i1+1] & EDGE_RIGHT))
  186.     {
  187.       int increment;    /* fractional part */
  188.       int denom;        /* denominator of fraction */
  189.       int step;        /* integral step */
  190.       int frac;        /* fractional step */
  191.       int reverse;
  192.  
  193.       /* find bottom of gap */
  194.       i2 = i1+2;
  195.       while (!(present[i2] & EDGE_RIGHT) && i2 < b->height) i2++;
  196.       
  197.       if (i2 < b->height)
  198.         {
  199.           denom = i2-i1;
  200.           x1 = b->data[i1].right;
  201.           x2 = b->data[i2].right;
  202.           step = (x2-x1)/denom;
  203.           frac = x2-x1 - step*denom;
  204.           if (frac < 0)
  205.         {
  206.           frac = -frac;
  207.           reverse = 1;
  208.         }
  209.           else
  210.         reverse = 0;
  211.           
  212.           increment = 0;
  213.           for (i=i1+1; i<i2; i++)
  214.         {
  215.           x1 += step;
  216.           increment += frac;
  217.           if (increment >= denom)
  218.             {
  219.               increment -= denom;
  220.               x1 += reverse ? -1 : 1;
  221.             }
  222.           if (reverse && increment != 0)
  223.             b->data[i].right = x1 - 1;
  224.           else
  225.             b->data[i].right = x1;
  226.         }
  227.         }
  228.       i1 = i2-1;        /* advance to next possibility */
  229.     }
  230.     }
  231.  
  232. }
  233.  
  234. static void
  235. airbrush_blob_make_convex (AirBrushBlob *b, EdgeType *present)
  236. {
  237.   int x1, x2, y1, y2, i1, i2;
  238.   int i;
  239.   int start;
  240.  
  241.   /* Walk through edges, deleting points that aren't on convex hull */
  242.  
  243.   start = 0;
  244.   while (!(present[start])) start++;
  245.  
  246.   /*    left edge */
  247.  
  248.   i1 = start-1; 
  249.   i2 = start;
  250.   x1 = b->data[start].left - b->data[start].right;
  251.   y1 = 0;
  252.   
  253.   for (i=start+1;i<b->height;i++)
  254.     {
  255.       if (!(present[i] & EDGE_LEFT))
  256.     continue;
  257.  
  258.       x2 = b->data[i].left - b->data[i2].left;
  259.       y2 = i-i2;
  260.       
  261.       while (x2*y1 - x1*y2 < 0) /* clockwise rotation */
  262.     {
  263.       present[i2] &= ~EDGE_LEFT;
  264.       i2 = i1;
  265.       while (!(present[--i1] & EDGE_LEFT) && i1>=start);
  266.  
  267.       if (i1<start)
  268.         {
  269.           x1 = b->data[start].left - b->data[start].right;
  270.           y1 = 0;
  271.         }
  272.       else
  273.         {
  274.           x1 = b->data[i2].left - b->data[i1].left;
  275.           y1 = i2 - i1;
  276.         }
  277.       x2 = b->data[i].left - b->data[i2].left;
  278.       y2 = i - i2;
  279.     }
  280.       x1 = x2;
  281.       y1 = y2;
  282.       i1 = i2;
  283.       i2 = i;
  284.     }
  285.  
  286.   /*     Right edge */
  287.  
  288.   i1 = start -1; 
  289.   i2 = start;
  290.   x1 = b->data[start].right - b->data[start].left;
  291.   y1 = 0;
  292.   
  293.   for (i=start+1;i<b->height;i++)
  294.     {
  295.       if (!(present[i] & EDGE_RIGHT))
  296.     continue;
  297.  
  298.       x2 = b->data[i].right - b->data[i2].right;
  299.       y2 = i-i2;
  300.       
  301.       while (x2*y1 - x1*y2 > 0) /* counter-clockwise rotation */
  302.     {
  303.       present[i2] &= ~EDGE_RIGHT;
  304.       i2 = i1;
  305.       while (!(present[--i1] & EDGE_RIGHT) && i1>=start);
  306.  
  307.       if (i1<start)
  308.         {
  309.           x1 = b->data[start].right - b->data[start].left;
  310.           y1 = 0;
  311.         }
  312.       else
  313.         {
  314.           x1 = b->data[i2].right - b->data[i1].right;
  315.           y1 = i2 - i1;
  316.         }
  317.       x2 = b->data[i].right - b->data[i2].right;
  318.       y2 = i - i2;
  319.     }
  320.       x1 = x2;
  321.       y1 = y2;
  322.       i1 = i2;
  323.       i2 = i;
  324.     }
  325.  
  326.   airbrush_blob_fill (b, present);
  327. }
  328.  
  329. AirBrushBlob *
  330. airbrush_blob_convex_union (AirBrushBlob *b1, AirBrushBlob *b2)
  331. {
  332.   AirBrushBlob *result;
  333.   int y;
  334.   int i, j;
  335.   EdgeType *present;
  336.  
  337.  
  338.   /* Create the storage for the result */
  339.  
  340.   y = MIN(b1->y,b2->y);
  341.   result = airbrush_blob_new (y, MAX(b1->y+b1->height,b2->y+b2->height)-y);
  342.  
  343.   if (result->height == 0)
  344.     return result;
  345.  
  346.   present = g_new0 (EdgeType, result->height);
  347.  
  348.   /* Initialize spans from original objects */
  349.  
  350.   for (i=0, j=b1->y-y; i<b1->height; i++,j++)
  351.     {
  352.       if (b1->data[i].right >= b1->data[i].left)
  353.     {
  354.       present[j] = EDGE_LEFT | EDGE_RIGHT;
  355.       result->data[j].left = b1->data[i].left;
  356.       result->data[j].right = b1->data[i].right;
  357.     }
  358.     }
  359.  
  360.   for (i=0, j=b2->y-y; i<b2->height; i++,j++)
  361.     {
  362.       if (b2->data[i].right >= b2->data[i].left)
  363.     {
  364.       if (present[j])
  365.         {
  366.           if (result->data[j].left > b2->data[i].left)
  367.         result->data[j].left = b2->data[i].left;
  368.           if (result->data[j].right < b2->data[i].right)
  369.         result->data[j].right = b2->data[i].right;
  370.         }
  371.       else
  372.         {
  373.           present[j] = EDGE_LEFT | EDGE_RIGHT;
  374.           result->data[j].left = b2->data[i].left;
  375.           result->data[j].right = b2->data[i].right;
  376.         }
  377.     }
  378.     }
  379.   
  380.   airbrush_blob_make_convex (result, present);
  381.  
  382.   g_free (present);
  383.   return result;
  384. }
  385.  
  386. /* You must be able to divide TABLE_SIZE with 4*/
  387.  
  388. #define TABLE_SIZE 256
  389. #define TABLE_QUARTER TABLE_SIZE/4   
  390.  
  391. #define ELLIPSE_SHIFT 2
  392. #define TABLE_SHIFT 14
  393. #define TOTAL_SHIFT (ELLIPSE_SHIFT + TABLE_SHIFT)
  394.  
  395. static int trig_initialized = 0;
  396. static int trig_table[TABLE_SIZE];
  397. #define POWFAC 0.999
  398.  
  399.  
  400.  
  401. /* Scan convert an ellipse specified by _offsets_ of major and
  402.    minor axes, and by center into a airbrush_blob */
  403.  
  404. /* Warning UGLY code ahead :-)*/
  405.  
  406. AirBrushBlob *
  407. airbrush_blob_ellipse (double xc, double yc, double xt, double yt, double xr, double yr, double xb, double yb, double xl, double yl)
  408. {
  409.   int i;
  410.   AirBrushBlob *rma, *rmi, *rtot;
  411.   gint maxyma, minyma, maxymi, minymi;
  412.   gint step;
  413.   double max_radius;
  414.   double ma_ang1, ma_ang2;
  415.   double x1, x2, y1, y2;
  416.   double xtotma, ytotma;
  417.   double xcma, ycma, ytma, xrma, ybma, xlma;
  418.   double xcmi, ycmi, ytmi, xrmi, ybmi, xlmi;
  419.   double mapoint_i, mapoint; 
  420.  
  421.   gint xcma_shift, ycma_shift;
  422.   gint xcmi_shift, ycmi_shift; 
  423.   gint ytma_shift, ytmi_shift;
  424.   gint xrma_shift, xrmi_shift;
  425.   gint ybma_shift, ybmi_shift;
  426.   gint xlma_shift, xlmi_shift;
  427.  
  428.   EdgeType *presentma;
  429.   EdgeType *presentmi;
  430.  
  431.  
  432.   if ((yt == yb) && (xr == xl) && (yt == xr))
  433.     {
  434.     /*Zero*/
  435.  
  436.     ytma = ytmi = xrma = xrmi = ybma = ybmi = xlma = xlmi = yt;
  437.     ycma = ycmi = yc;
  438.     xcma = xcmi = xc;
  439.  
  440.     }
  441.   else if (xr == xl)
  442.     {
  443.     if (yt > yb)
  444.         {
  445.         /*South*/
  446.  
  447.         /*The Max circle*/ 
  448.         ytma = ybma = xrma = xlma = xl;
  449.         mapoint_i = (((yt * yt) / yb) - yt);
  450.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);    
  451.         xcma = xc;
  452.         ycma = yc + mapoint;
  453.  
  454.         /*The Min Circle*/
  455.         ytmi = xrmi = ybmi = xlmi = xl/2;
  456.         xcmi = xc;
  457.         ycmi = yc - mapoint/2;
  458.  
  459.         }
  460.     else
  461.             {    
  462.         /*North*/
  463.  
  464.                 /*The Max circle*/
  465.                 ytma = ybma = xrma = xlma = xl;
  466.                 mapoint_i = (((yb * yb) / yt) - yb);
  467.                 mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  468.                 xcma = xc;
  469.                 ycma = yc - mapoint;
  470.  
  471.                 /*The Min Circle*/
  472.                 ytmi = xrmi = ybmi = xlmi = xl/2;
  473.                 xcmi = xc;
  474.                 ycmi = yc + mapoint/2; 
  475.  
  476.         }    
  477.     }     
  478.   else if (yt == yb)
  479.     {
  480.     if (xr > xl)
  481.         {
  482.         /*East*/
  483.         
  484.         /*The Max circle*/
  485.         ytma = ybma = xrma = xlma = yt;
  486.         mapoint_i = (((xr * xr) /xl) -xr);
  487.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  488.         xcma = mapoint + xc;
  489.         ycma = yc;
  490.  
  491.         /*The Min Circle*/
  492.         ytmi = ybmi = xrmi = xlmi = yt/2;
  493.         xcmi = xc - mapoint/2;     
  494.         ycmi = yc;
  495.         
  496.         }
  497.     else
  498.         {
  499.         /*West*/
  500.  
  501.                 /*The Max circle*/
  502.                 ytma = ybma = xrma = xlma = yt;
  503.                 mapoint_i = (((xl * xl) /xr) - xl);
  504.                 mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  505.                 xcma = xc - mapoint;
  506.                 ycma = yc;
  507.   
  508.  
  509.                 /*The Min Circle*/
  510.                 ytmi = ybmi = xrmi = xlmi = yt/2;
  511.                 xcmi = xc + mapoint/2;
  512.                 ycmi = yc; 
  513.         
  514.         }
  515.     }
  516.   else if ((yt > yb) && (xr > xl))
  517.       {
  518.     /*SouthEast*/
  519.  
  520.         /*The Max circle*/
  521.         ma_ang1 = atan(yt/xr);
  522.         x1 = cos(ma_ang1) * xl;
  523.         y1 = sin(ma_ang1) * yt;
  524.         ma_ang2 = G_PI_2 - ma_ang1;
  525.         x2 = cos(ma_ang2) * xr;
  526.         y2 = sin(ma_ang2) * yb;
  527.         xtotma = x1 + x2;
  528.         ytotma = y1 + y2;
  529.         ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
  530.         mapoint_i = (((yt * yt + xr * xr) / hypot(yb, xl)) - hypot(yt, xr));
  531.         mapoint = mapoint_i  * pow(POWFAC , mapoint_i);
  532.         xcma = xc + (cos(ma_ang1) * mapoint);
  533.         ycma = yc + (sin(ma_ang1) * mapoint);
  534.  
  535.         /*The Min Circle*/
  536.         ytmi = xrmi = ybmi = xlmi = hypot(yb, xl)/2;
  537.         xcmi = xc - (cos(ma_ang1) * mapoint * 0.5);
  538.         ycmi = yc - (sin(ma_ang1) * mapoint * 0.5);         
  539.  
  540.     }
  541.   else if ((yt > yb) && (xl > xr))
  542.         {    
  543.     /*SouthWest*/
  544.  
  545.         /*The Max circle*/
  546.         ma_ang1 = atan(yt/xl);
  547.         x1 = cos(ma_ang1) * xr;
  548.         y1 = sin(ma_ang1) * yt;
  549.         ma_ang2 = G_PI_2 - ma_ang1;
  550.         x2 = cos(ma_ang2) * xl;
  551.         y2 = sin(ma_ang2) * yb;
  552.         xtotma = x1 + x2;
  553.         ytotma = y1 + y2;
  554.         ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
  555.         mapoint_i = (((yt * yt + xl * xl) / hypot(yb, xr)) - hypot(yt, xl));
  556.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  557.         xcma = xc - (cos(ma_ang1) * mapoint);
  558.         ycma = yc + (sin(ma_ang1) * mapoint);
  559.  
  560.         /*The Min Circle*/
  561.         ytmi = xrmi = ybmi = xlmi = hypot(yb, xr)/2;
  562.         xcmi = xc + (cos(ma_ang1) * mapoint * 0.5);
  563.         ycmi = yc - (sin(ma_ang1) * mapoint * 0.5);       
  564.  
  565.     }    
  566.   else if ((yb > yt) && (xl > xr))
  567.     {    
  568.     /*NorthWest*/
  569.  
  570.         /*The Max circle*/
  571.         ma_ang1 = atan(yb/xl);
  572.         x1 = cos(ma_ang1) * xl;
  573.         y1 = sin(ma_ang1) * yt;
  574.         ma_ang2 = G_PI_2 - ma_ang1;
  575.         x2 = cos(ma_ang2) * xr;
  576.         y2 = sin(ma_ang2) * yb;
  577.         xtotma = x1 + x2;
  578.         ytotma = y1 + y2;
  579.         ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
  580.         mapoint_i = (((yb * yb + xl * xl) / hypot(yt, xr)) - hypot(yb, xl));
  581.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  582.         xcma = xc - (cos(ma_ang1) * mapoint);
  583.         ycma = yc - (sin(ma_ang1) * mapoint);
  584.  
  585.         /*The Min Circle*/
  586.         ytmi = xrmi = ybmi = xlmi = hypot(yt, xr)/2;
  587.         xcmi = xc + (cos(ma_ang1) * mapoint * 0.5);
  588.         ycmi = yc + (sin(ma_ang1) * mapoint * 0.5);       
  589.  
  590.     }    
  591.   else 
  592. /*if ((yb > yt) && (xr > xl))*/
  593.     {
  594.     /*NorthEast*/
  595.  
  596.         /*The Max circle*/
  597.         ma_ang1 = atan(yb/xr);
  598.         x1 = cos(ma_ang1) * xr;
  599.         y1 = sin(ma_ang1) * yt;
  600.         ma_ang2 = G_PI_2 - ma_ang1;
  601.         x2 = cos(ma_ang2) * xl;
  602.         y2 = sin(ma_ang2) * yb;
  603.         xtotma = x1 + x2;
  604.         ytotma = y1 + y2;
  605.         ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
  606.         mapoint_i = (((yb * yb + xr * xr) / hypot(yt, xl)) - hypot(yb, xr));
  607.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  608.         xcma = xc + (cos(ma_ang1) * mapoint);
  609.         ycma = yc - (sin(ma_ang1) * mapoint);
  610.  
  611.         /*The Min Circle*/
  612.         ytmi = xrmi = ybmi = xlmi = hypot(yt, xl)/2;
  613.         xcmi = xc - (cos(ma_ang1) * mapoint * 0.5);
  614.         ycmi = yc + (sin(ma_ang1) * mapoint * 0.5);       
  615.  
  616.     }
  617.   if (ytmi <= 0)
  618.     {
  619.     ytmi = ybmi = xrmi = xlmi = 1;
  620.     } 
  621.         
  622.   if (ytma <= 0)
  623.         {
  624.         ytma = ybma = xrma = xlma = 1;
  625.         }     
  626.   
  627.   if (!trig_initialized)
  628.     {
  629.       trig_initialized = 1;
  630.       for (i=0; i<256; i++)
  631.     trig_table[i] = 0.5 + sin(i * (G_PI / 128.0)) * (1 << TABLE_SHIFT);
  632.     }
  633.  
  634.  
  635. /*Make the Max circle*/
  636.    
  637.   maxyma = ceil (ycma + fabs (ytma));
  638.   minyma = floor (ycma - fabs (ybma));
  639.  
  640.  
  641.  
  642.   rma = airbrush_blob_new (minyma, maxyma - minyma + 1);
  643.   
  644.   
  645.   presentma = g_new0 (EdgeType, rma->height);
  646.  
  647.   max_radius = ytma;
  648.  
  649.   step = TABLE_SIZE;
  650.  
  651.   while (step > 1 && (TABLE_SIZE / step < 4*max_radius))
  652.     step >>= 1;
  653.  
  654.   /* Fill in the edge points */
  655.  
  656.   xcma_shift = 0.5 + xcma * (1 << TOTAL_SHIFT);
  657.   ycma_shift = 0.5 + ycma * (1 << TOTAL_SHIFT);
  658.   ytma_shift = 0.5 + ytma * (1 << ELLIPSE_SHIFT);
  659.   xrma_shift = 0.5 + xrma * (1 << ELLIPSE_SHIFT);
  660.   ybma_shift = 0.5 + ybma * (1 << ELLIPSE_SHIFT); 
  661.   xlma_shift = 0.5 + xlma * (1 << ELLIPSE_SHIFT);
  662.  
  663.  
  664.   for (i = 0 ; i < TABLE_SIZE ; i += step)
  665.     {
  666.  
  667.       gint x, y, yi, dydi;
  668.  
  669.       gint s = trig_table[i];
  670.       gint c = trig_table[(TABLE_SIZE + TABLE_SIZE/4 - i) % TABLE_SIZE];
  671.  
  672.       if (i < TABLE_QUARTER )
  673.         {
  674.           x = (xcma_shift + c * xrma_shift +
  675.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  676.           yi = (ycma_shift + s * ytma_shift +
  677.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  678.           y = yi -  rma->y;
  679.           dydi = 1;
  680.  
  681.         }
  682.       else if ( i < (2 * TABLE_QUARTER) )
  683.         {
  684.           x = (xcma_shift + c * xlma_shift +
  685.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  686.           yi = (ycma_shift + s * ytma_shift +
  687.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  688.  
  689.           y = yi - rma->y; 
  690.            
  691.           dydi = -1;
  692.         }
  693.       else if ( i < (3 * TABLE_QUARTER) )
  694.         {
  695.           x = (xcma_shift + c * xlma_shift +
  696.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  697.           yi = (ycma_shift + s * ybma_shift +
  698.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; 
  699.           y = yi - rma->y;
  700.           dydi = -1;
  701.  
  702.         }
  703.       else
  704.         {
  705.           x = (xcma_shift + c * xrma_shift +
  706.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  707.           y = ((ycma_shift + s * ybma_shift +
  708.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT) - rma->y;
  709.  
  710.           dydi = 1;
  711.  
  712.         }
  713.  
  714.  
  715.  
  716.  
  717.       if (dydi <= 0) /* left edge */
  718.     {
  719.       if (presentma[y] & EDGE_LEFT)
  720.         {
  721.           rma->data[y].left = MIN (rma->data[y].left, x);
  722.         }
  723.       else
  724.         {
  725.           presentma[y] |= EDGE_LEFT;
  726.           rma->data[y].left = x;
  727.         }
  728.     }
  729.       
  730.       if (dydi > 0) /* right edge */
  731.     {
  732.       if (presentma[y] & EDGE_RIGHT)
  733.         {
  734.           rma->data[y].right = MAX (rma->data[y].right, x);
  735.         }
  736.       else
  737.         {
  738.           presentma[y] |= EDGE_RIGHT;
  739.           rma->data[y].right = x;
  740.         }
  741.     }
  742.     }
  743.  
  744.   /* Now fill in missing points */
  745.  
  746.   airbrush_blob_fill (rma, presentma);
  747.   g_free (presentma);
  748.  
  749. /*Make the Min circle*/
  750.  
  751.  
  752.   maxymi = ceil (ycmi + fabs (ytmi));
  753.   minymi = floor (ycmi - fabs (ybmi));
  754.  
  755.  
  756.   rmi = airbrush_blob_new (minymi, maxymi - minymi + 1);
  757.  
  758.  
  759.   presentmi = g_new0 (EdgeType, rmi->height);
  760.  
  761.   max_radius = ytmi;
  762.  
  763.   step = TABLE_SIZE;
  764.  
  765.   while (step > 1 && (TABLE_SIZE / step < 4*max_radius))
  766.     step >>= 1;
  767.  
  768.   /* Fill in the edge points */
  769.  
  770.   xcmi_shift = 0.5 + xcmi * (1 << TOTAL_SHIFT);
  771.   ycmi_shift = 0.5 + ycmi * (1 << TOTAL_SHIFT);
  772.   ytmi_shift = 0.5 + ytmi * (1 << ELLIPSE_SHIFT);
  773.   xrmi_shift = 0.5 + xrmi * (1 << ELLIPSE_SHIFT);
  774.   ybmi_shift = 0.5 + ybmi * (1 << ELLIPSE_SHIFT);
  775.   xlmi_shift = 0.5 + xlmi * (1 << ELLIPSE_SHIFT);
  776.  
  777.  
  778.  
  779.   for (i = 0 ; i < TABLE_SIZE ; i += step)
  780.     {
  781.  
  782.       gint x, y, yi, dydi;
  783.  
  784.       gint s = trig_table[i];
  785.       gint c = trig_table[(TABLE_SIZE + TABLE_SIZE/4 - i) % TABLE_SIZE];
  786.  
  787.       if (i < TABLE_QUARTER )
  788.         {
  789.           x = (xcmi_shift + c * xrmi_shift +
  790.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  791.           yi = (ycmi_shift + s * ytmi_shift +
  792.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  793.           y = yi -  rmi->y;
  794.           dydi = 1;
  795.  
  796.         }
  797.       else if ( i < (2 * TABLE_QUARTER) )
  798.         {
  799.           x = (xcmi_shift + c * xlmi_shift +
  800.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  801.           yi = (ycmi_shift + s * ytmi_shift +
  802.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  803.  
  804.           y = yi - rmi->y;
  805.  
  806.           dydi = -1;
  807.         }
  808.       else if ( i < (3 * TABLE_QUARTER) )
  809.         {
  810.           x = (xcmi_shift + c * xlmi_shift +
  811.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  812.           yi = (ycmi_shift + s * ybmi_shift +
  813.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  814.           y = yi - rmi->y;
  815.           dydi = -1;
  816.  
  817.         }
  818.       else
  819.         {
  820.           x = (xcmi_shift + c * xrmi_shift +
  821.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
  822.           y = ((ycmi_shift + s * ybmi_shift +
  823.                (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT) - rmi->y;
  824.  
  825.           dydi = 1;
  826.  
  827.         }
  828.  
  829.  
  830.  
  831.  
  832.       if (dydi <= 0) /* left edge */
  833.         {
  834.           if (presentmi[y] & EDGE_LEFT)
  835.             {
  836.               rmi->data[y].left = MIN (rmi->data[y].left, x);
  837.             }
  838.           else
  839.             {
  840.               presentmi[y] |= EDGE_LEFT;
  841.               rmi->data[y].left = x;
  842.             }
  843.         }
  844.  
  845.       if (dydi > 0) /* right edge */
  846.         {
  847.           if (presentmi[y] & EDGE_RIGHT)
  848.             {
  849.               rmi->data[y].right = MAX (rmi->data[y].right, x);
  850.             }
  851.           else
  852.             {
  853.               presentmi[y] |= EDGE_RIGHT;
  854.               rmi->data[y].right = x;
  855.             }
  856.         }
  857.     }
  858.  
  859.   /* Now fill in missing points */
  860.  
  861.   airbrush_blob_fill (rmi, presentmi);
  862.   g_free (presentmi);                     
  863.  
  864.   rtot = airbrush_blob_convex_union(rma, rmi);
  865.  
  866.   g_free (rma);
  867.   g_free (rmi);    
  868.  
  869.   return rtot;
  870. }
  871.  
  872. void
  873. airbrush_blob_bounds(AirBrushBlob *b, int *x, int *y, int *width, int *height)
  874. {
  875.   int i;
  876.   int x0, x1, y0, y1;
  877.  
  878.   i = 0;
  879.   while (i<b->height && b->data[i].left > b->data[i].right)
  880.     i++;
  881.  
  882.   if (i<b->height)
  883.     {
  884.       y0 = b->y + i;
  885.       x0 = b->data[i].left;
  886.       x1 = b->data[i].right + 1;
  887.       while (i<b->height && b->data[i].left <= b->data[i].right)
  888.     {
  889.       x0 = MIN(b->data[i].left, x0);
  890.       x1 = MAX(b->data[i].right+1, x1);
  891.       i++;
  892.     }
  893.       y1 = b->y + i;
  894.     }
  895.   else
  896.     {
  897.       x0 = y0 = 0;
  898.       x1 = y1 = 0;
  899.     }
  900.  
  901.   *x = x0;
  902.   *y = y0;
  903.   *width = x1 - x0;
  904.   *height = y1 - y0;
  905. }
  906.  
  907. void
  908. airbrush_blob_dump(AirBrushBlob *b) {
  909.  
  910.   int i,j;
  911.  
  912.  
  913.   for (i=0; i<b->height; i++)
  914.     {
  915.       for (j=0;j<b->data[i].left;j++)
  916.     putchar(' ');
  917.       for (j=b->data[i].left;j<=b->data[i].right;j++)
  918.     putchar('*');
  919.       putchar('\n');
  920.     }
  921. }
  922.  
  923. /* This is just a first try to see how it works i.e ugly code :-) */
  924.  
  925.  
  926. AirBlob *
  927. create_air_blob (double xc,
  928.          double yc,
  929.          double xt,
  930.          double yt,
  931.          double xr,
  932.          double yr,
  933.          double xb,
  934.          double yb,
  935.          double xl,
  936.          double yl,
  937.          double direction_abs,
  938.          double direction)
  939. {
  940.   AirBlob *air_blob;
  941.   double ma_ang1, ma_ang2;
  942.   double x1, x2, y1, y2;
  943.   double xtotma, ytotma;
  944.   double xcma, ycma, ytma, xrma, ybma, xlma;
  945.   double xcmi, ycmi, ytmi, xrmi, ybmi, xlmi;
  946.   double mapoint_i, mapoint; 
  947.   
  948.   air_blob = airblob_new(1);
  949.  
  950.   air_blob->direction_abs = direction_abs;
  951.   air_blob->direction = direction;
  952.   air_blob->ycenter = yc;
  953.   air_blob->xcenter = xc;
  954.  
  955.   if ((yt == yb) && (xr == xl) && (yt == xr))
  956.     {
  957.     /*Zero*/
  958.  
  959.     ytma = ytmi = xrma = xrmi = ybma = ybmi = xlma = xlmi = yt;
  960.     ycma = ycmi = yc;
  961.     xcma = xcmi = xc;
  962.     
  963.     air_blob->main_line.size = yt;
  964.     air_blob->minor_line.size = yt;
  965.     
  966.      air_blob->maincross_line.size = yt * 2;
  967.     air_blob->maincross_line.dist = 0.0;
  968.  
  969.      air_blob->minorcross_line.size = yt * 2;
  970.     air_blob->minorcross_line.dist = 0.0;
  971.  
  972.     air_blob->direction = G_PI_2;
  973.  
  974.     }
  975.   else if (xr == xl)
  976.     {
  977.     if (yt > yb)
  978.         {
  979.         /*South*/
  980.  
  981.         /*The Max circle*/ 
  982.         ytma = ybma = xrma = xlma = xl;
  983.         mapoint_i = (((yt * yt) / yb) - yt);
  984.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);    
  985.         xcma = xc;
  986.         ycma = yc + mapoint;
  987.  
  988.         /*The Min Circle*/
  989.         ytmi = xrmi = ybmi = xlmi = xl/2;
  990.         xcmi = xc;
  991.         ycmi = yc - mapoint/2;
  992.  
  993.         air_blob->main_line.size = mapoint + xl;
  994.         air_blob->minor_line.size = mapoint/2 + xl/2;
  995.     
  996.         air_blob->maincross_line.size = xl * 2;
  997.         air_blob->maincross_line.dist = mapoint;
  998.  
  999.         air_blob->minorcross_line.size = xl/2;
  1000.         air_blob->minorcross_line.dist = mapoint/2;
  1001.  
  1002.  
  1003.  
  1004.         }
  1005.     else
  1006.             {    
  1007.         /*North*/
  1008.  
  1009.                 /*The Max circle*/
  1010.                 ytma = ybma = xrma = xlma = xl;
  1011.                 mapoint_i = (((yb * yb) / yt) - yb);
  1012.                 mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  1013.                 xcma = xc;
  1014.                 ycma = yc - mapoint;
  1015.  
  1016.                 /*The Min Circle*/
  1017.                 ytmi = xrmi = ybmi = xlmi = xl/2;
  1018.                 xcmi = xc;
  1019.                 ycmi = yc + mapoint/2; 
  1020.  
  1021.  
  1022.         air_blob->main_line.size = mapoint + xl;
  1023.         air_blob->minor_line.size = mapoint/2 + xl/2;
  1024.     
  1025.         air_blob->maincross_line.size = xl * 2;
  1026.         air_blob->maincross_line.dist = mapoint;
  1027.  
  1028.         air_blob->minorcross_line.size = xl/2;
  1029.         air_blob->minorcross_line.dist = mapoint/2;
  1030.  
  1031.  
  1032.         }    
  1033.     }     
  1034.   else if (yt == yb)
  1035.     {
  1036.     if (xr > xl)
  1037.         {
  1038.         /*East*/
  1039.         
  1040.         /*The Max circle*/
  1041.         ytma = ybma = xrma = xlma = yt;
  1042.         mapoint_i = (((xr * xr) /xl) -xr);
  1043.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  1044.         xcma = mapoint + xc;
  1045.         ycma = yc;
  1046.  
  1047.         /*The Min Circle*/
  1048.         ytmi = ybmi = xrmi = xlmi = yt/2;
  1049.         xcmi = xc - mapoint/2;     
  1050.         ycmi = yc;
  1051.  
  1052.         air_blob->main_line.size = mapoint + yt;
  1053.         air_blob->minor_line.size = mapoint/2 + yt/2;
  1054.  
  1055.         air_blob->maincross_line.size = xl * 2;
  1056.         air_blob->maincross_line.dist = mapoint;
  1057.  
  1058.         air_blob->minorcross_line.size = xl/2;
  1059.         air_blob->minorcross_line.dist = mapoint/2;
  1060.  
  1061.         
  1062.         }
  1063.     else
  1064.         {
  1065.         /*West*/
  1066.  
  1067.                 /*The Max circle*/
  1068.                 ytma = ybma = xrma = xlma = yt;
  1069.                 mapoint_i = (((xl * xl) /xr) - xl);
  1070.                 mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  1071.                 xcma = xc - mapoint;
  1072.                 ycma = yc;
  1073.   
  1074.  
  1075.                 /*The Min Circle*/
  1076.                 ytmi = ybmi = xrmi = xlmi = yt/2;
  1077.                 xcmi = xc + mapoint/2;
  1078.                 ycmi = yc; 
  1079.  
  1080.         air_blob->main_line.size = mapoint + yt;
  1081.         air_blob->minor_line.size = mapoint/2 + yt/2;
  1082.     
  1083.              air_blob->maincross_line.size = xl * 2;
  1084.         air_blob->maincross_line.dist = mapoint;
  1085.  
  1086.         air_blob->minorcross_line.size = xl/2;
  1087.         air_blob->minorcross_line.dist = mapoint/2;
  1088.  
  1089.         
  1090.         }
  1091.     }
  1092.   else if ((yt > yb) && (xr > xl))
  1093.       {
  1094.     /*SouthEast*/
  1095.  
  1096.         /*The Max circle*/
  1097.         ma_ang1 = atan(yt/xr);
  1098.         x1 = cos(ma_ang1) * xl;
  1099.         y1 = sin(ma_ang1) * yt;
  1100.         ma_ang2 = G_PI_2 - ma_ang1;
  1101.         x2 = cos(ma_ang2) * xr;
  1102.         y2 = sin(ma_ang2) * yb;
  1103.         xtotma = x1 + x2;
  1104.         ytotma = y1 + y2;
  1105.         ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
  1106.         mapoint_i = (((yt * yt + xr * xr) / hypot(yb, xl)) - hypot(yt, xr));
  1107.         mapoint = mapoint_i  * pow(POWFAC , mapoint_i);
  1108.         xcma = xc + (cos(ma_ang1) * mapoint);
  1109.         ycma = yc + (sin(ma_ang1) * mapoint);
  1110.  
  1111.         /*The Min Circle*/
  1112.         ytmi = xrmi = ybmi = xlmi = hypot(yb, xl)/2;
  1113.         xcmi = xc - (cos(ma_ang1) * mapoint * 0.5);
  1114.         ycmi = yc - (sin(ma_ang1) * mapoint * 0.5);         
  1115.  
  1116.  
  1117.     air_blob->main_line.size = mapoint + xlma;
  1118.     air_blob->minor_line.size = mapoint/2 + xlmi;
  1119.  
  1120.     
  1121.     air_blob->maincross_line.size = xlma * 2;
  1122.     air_blob->maincross_line.dist = mapoint;
  1123.  
  1124.     air_blob->minorcross_line.size = xlmi;
  1125.     air_blob->minorcross_line.dist = mapoint/2;
  1126.  
  1127.  
  1128.  
  1129.  
  1130.     }
  1131.   else if ((yt > yb) && (xl > xr))
  1132.         {    
  1133.     /*SouthWest*/
  1134.  
  1135.         /*The Max circle*/
  1136.         ma_ang1 = atan(yt/xl);
  1137.         x1 = cos(ma_ang1) * xr;
  1138.         y1 = sin(ma_ang1) * yt;
  1139.         ma_ang2 = G_PI_2 - ma_ang1;
  1140.         x2 = cos(ma_ang2) * xl;
  1141.         y2 = sin(ma_ang2) * yb;
  1142.         xtotma = x1 + x2;
  1143.         ytotma = y1 + y2;
  1144.         ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
  1145.         mapoint_i = (((yt * yt + xl * xl) / hypot(yb, xr)) - hypot(yt, xl));
  1146.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  1147.         xcma = xc - (cos(ma_ang1) * mapoint);
  1148.         ycma = yc + (sin(ma_ang1) * mapoint);
  1149.  
  1150.         /*The Min Circle*/
  1151.         ytmi = xrmi = ybmi = xlmi = hypot(yb, xr)/2;
  1152.         xcmi = xc + (cos(ma_ang1) * mapoint * 0.5);
  1153.         ycmi = yc - (sin(ma_ang1) * mapoint * 0.5);       
  1154.  
  1155.     air_blob->main_line.size = mapoint + xlma;
  1156.     air_blob->minor_line.size = mapoint/2 + xlmi;
  1157.  
  1158.     air_blob->maincross_line.size = xlma * 2;
  1159.     air_blob->maincross_line.dist = mapoint;
  1160.  
  1161.     air_blob->minorcross_line.size = xlmi;
  1162.     air_blob->minorcross_line.dist = mapoint/2;
  1163.  
  1164.     }    
  1165.   else if ((yb > yt) && (xl > xr))
  1166.     {    
  1167.     /*NorthWest*/
  1168.  
  1169.         /*The Max circle*/
  1170.         ma_ang1 = atan(yb/xl);
  1171.         x1 = cos(ma_ang1) * xl;
  1172.         y1 = sin(ma_ang1) * yt;
  1173.         ma_ang2 = G_PI_2 - ma_ang1;
  1174.         x2 = cos(ma_ang2) * xr;
  1175.         y2 = sin(ma_ang2) * yb;
  1176.         xtotma = x1 + x2;
  1177.         ytotma = y1 + y2;
  1178.         ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
  1179.         mapoint_i = (((yb * yb + xl * xl) / hypot(yt, xr)) - hypot(yb, xl));
  1180.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  1181.         xcma = xc - (cos(ma_ang1) * mapoint);
  1182.         ycma = yc - (sin(ma_ang1) * mapoint);
  1183.  
  1184.         /*The Min Circle*/
  1185.         ytmi = xrmi = ybmi = xlmi = hypot(yt, xr)/2;
  1186.         xcmi = xc + (cos(ma_ang1) * mapoint * 0.5);
  1187.         ycmi = yc + (sin(ma_ang1) * mapoint * 0.5);
  1188.  
  1189.     air_blob->main_line.size = mapoint + xlma;
  1190.     air_blob->minor_line.size = mapoint/2 + xlmi;
  1191.  
  1192.     air_blob->maincross_line.size = xlma * 2;
  1193.     air_blob->maincross_line.dist = mapoint;
  1194.  
  1195.     air_blob->minorcross_line.size = xlmi;
  1196.     air_blob->minorcross_line.dist = mapoint/2;
  1197.  
  1198.  
  1199.        
  1200.  
  1201.     }    
  1202.   else 
  1203. /*if ((yb > yt) && (xr > xl))*/
  1204.     {
  1205.     /*NorthEast*/
  1206.  
  1207.         /*The Max circle*/
  1208.         ma_ang1 = atan(yb/xr);
  1209.         x1 = cos(ma_ang1) * xr;
  1210.         y1 = sin(ma_ang1) * yt;
  1211.         ma_ang2 = G_PI_2 - ma_ang1;
  1212.         x2 = cos(ma_ang2) * xl;
  1213.         y2 = sin(ma_ang2) * yb;
  1214.         xtotma = x1 + x2;
  1215.         ytotma = y1 + y2;
  1216.         ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2;
  1217.         mapoint_i = (((yb * yb + xr * xr) / hypot(yt, xl)) - hypot(yb, xr));
  1218.         mapoint = mapoint_i * pow(POWFAC, mapoint_i);
  1219.         xcma = xc + (cos(ma_ang1) * mapoint);
  1220.         ycma = yc - (sin(ma_ang1) * mapoint);
  1221.  
  1222.         /*The Min Circle*/
  1223.         ytmi = xrmi = ybmi = xlmi = hypot(yt, xl)/2;
  1224.         xcmi = xc - (cos(ma_ang1) * mapoint * 0.5);
  1225.         ycmi = yc + (sin(ma_ang1) * mapoint * 0.5);
  1226.  
  1227.     air_blob->main_line.size = mapoint + xlma;
  1228.     air_blob->minor_line.size = mapoint/2 + xlmi;
  1229.  
  1230.  
  1231.     air_blob->maincross_line.size = xlma * 2;
  1232.     air_blob->maincross_line.dist = mapoint;
  1233.  
  1234.     air_blob->minorcross_line.size = xlmi;
  1235.     air_blob->minorcross_line.dist = mapoint/2;
  1236.  
  1237.  
  1238.     }
  1239.  
  1240.   return air_blob;
  1241. }
  1242.  
  1243. AirLine *
  1244. create_air_line(AirBlob *airblob)
  1245. {
  1246.  
  1247.   int i;
  1248.   double xcenter, ycenter;
  1249.  
  1250.   double direction;
  1251.  
  1252.   double masupport, misupport;
  1253.   double ma_angsupport, mi_angsupport,  iang;
  1254.  
  1255.   int min_x, max_x;
  1256.   int min_y, max_y;
  1257.  
  1258.   AirLine *airline;
  1259.  
  1260.   /* 
  1261.      Yes I know I can do a cal of number of lines, but it is for
  1262.      the moment much easier to just set a side mem for 16 lines
  1263.   */
  1264.  
  1265.   airline = airline_new(1);
  1266.  
  1267.   xcenter = airblob->xcenter;
  1268.   ycenter = airblob->ycenter;
  1269.   
  1270.   airline->xcenter = xcenter/SUBSAMPLE;
  1271.   airline->ycenter = ycenter/SUBSAMPLE;
  1272.  
  1273.   direction = airblob->direction_abs;
  1274.  
  1275.   /*
  1276.     printf("Direction: %f\n", direction);
  1277.     printf("Xcenter: %f\n",xcenter/SUBSAMPLE);
  1278.     printf("Ycenter: %f\n",ycenter/SUBSAMPLE);
  1279.     printf("MaCr.dist: %f\n",airblob->maincross_line.dist);
  1280.     printf("MaCr.size: %f\n",airblob->maincross_line.size);
  1281.     printf("MiCr.dist: %f\n",airblob->minorcross_line.dist);
  1282.     printf("MiCr.size: %f\n",airblob->minorcross_line.size);
  1283.     printf("Ma.size: %f\n",airblob->main_line.size);
  1284.     printf("Mi.size: %f\n",airblob->minor_line.size);
  1285.   */
  1286.  
  1287.   if (direction == G_PI_2 || direction == G_PI)
  1288.     {
  1289.     direction = direction - 0.001;
  1290.     }
  1291.  
  1292.   if (direction == -G_PI_2 || direction == -G_PI)
  1293.     {
  1294.       direction = direction + 0.001;
  1295.     }
  1296.  
  1297.   if(direction == 0.0)
  1298.  
  1299.       {
  1300.  
  1301.     airline->line[0].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE;
  1302.     airline->line[0].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE;
  1303.     airline->line[1].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE;
  1304.     airline->line[1].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
  1305.  
  1306.     airline->line[2].x = (xcenter + airblob->main_line.size)/SUBSAMPLE;
  1307.     airline->line[2].y = (ycenter)/SUBSAMPLE;
  1308.     airline->line[3].x = (xcenter - airblob->minor_line.size)/SUBSAMPLE;
  1309.     airline->line[3].y = (ycenter)/SUBSAMPLE;
  1310.  
  1311.     airline->line[4].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE;
  1312.     airline->line[4].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
  1313.     airline->line[5].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE;
  1314.     airline->line[5].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
  1315.  
  1316.     airline->nlines = 6;
  1317.  
  1318.  
  1319.       }    
  1320.         
  1321.   else if(direction == G_PI_2)
  1322.  
  1323.       {
  1324.  
  1325.         airline->line[0].x = (xcenter - airblob->maincross_line.size/2)/SUBSAMPLE;
  1326.     airline->line[0].y = (ycenter - airblob->maincross_line.dist)/SUBSAMPLE;
  1327.     airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
  1328.     airline->line[1].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
  1329.  
  1330.     airline->line[2].x = (xcenter)/SUBSAMPLE;
  1331.     airline->line[2].y = (ycenter - airblob->main_line.size)/SUBSAMPLE;
  1332.     airline->line[3].x = (xcenter)/SUBSAMPLE;
  1333.     airline->line[3].y = (ycenter + airblob->minor_line.size)/SUBSAMPLE;
  1334.  
  1335.     airline->line[4].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE;
  1336.     airline->line[4].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE;
  1337.     airline->line[5].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE;
  1338.     airline->line[5].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
  1339.  
  1340.     airline->nlines = 6;
  1341.     printf("Hmm bummer G_PI_2\n");
  1342.  
  1343.       }
  1344.  
  1345.  
  1346.   else if(direction == G_PI)
  1347.  
  1348.     {
  1349.         airline->line[0].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
  1350.     airline->line[0].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
  1351.     airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
  1352.     airline->line[1].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
  1353.  
  1354.     airline->line[2].x = (xcenter - airblob->main_line.size)/SUBSAMPLE;
  1355.     airline->line[2].y = (ycenter)/SUBSAMPLE;
  1356.     airline->line[3].x = (xcenter + airblob->minor_line.size)/SUBSAMPLE;
  1357.     airline->line[3].y = (ycenter)/SUBSAMPLE;
  1358.  
  1359.     airline->line[4].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
  1360.     airline->line[4].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE;
  1361.     airline->line[5].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
  1362.     airline->line[5].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
  1363.  
  1364.     airline->nlines = 6;
  1365.  
  1366.     printf("Hmm bummer G_PI\n");
  1367.  
  1368.  
  1369.     }
  1370.  
  1371.   else if(direction == -G_PI_2)
  1372.  
  1373.     {
  1374.         airline->line[0].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
  1375.     airline->line[0].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
  1376.     airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
  1377.     airline->line[1].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
  1378.  
  1379.     airline->line[2].x = (xcenter)/SUBSAMPLE;
  1380.     airline->line[2].y = (ycenter + airblob->main_line.size)/SUBSAMPLE;
  1381.     airline->line[3].x = (xcenter)/SUBSAMPLE;
  1382.     airline->line[3].y = (ycenter - airblob->minor_line.size)/SUBSAMPLE;
  1383.  
  1384.     airline->line[4].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE;
  1385.     airline->line[4].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
  1386.     airline->line[5].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE;
  1387.     airline->line[5].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
  1388.  
  1389.     airline->nlines = 6;
  1390.  
  1391.     printf("Hmm bummer -G_PI_2\n");
  1392.  
  1393.  
  1394.  
  1395.     }
  1396.  
  1397.  
  1398.   else if(direction == -G_PI)
  1399.     
  1400.     {
  1401.         airline->line[0].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
  1402.     airline->line[0].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE;
  1403.     airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
  1404.     airline->line[1].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE;
  1405.  
  1406.     airline->line[2].x = (xcenter - airblob->main_line.size)/SUBSAMPLE;
  1407.     airline->line[2].y = (ycenter)/SUBSAMPLE;
  1408.     airline->line[3].x = (xcenter + airblob->minor_line.size)/SUBSAMPLE;
  1409.     airline->line[3].y = (ycenter)/SUBSAMPLE;
  1410.  
  1411.     airline->line[4].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE;
  1412.     airline->line[4].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE;
  1413.     airline->line[5].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE;
  1414.     airline->line[5].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE;
  1415.  
  1416.     airline->nlines = 6;
  1417.  
  1418.     printf("Hmm bummer -G_PI\n");
  1419.  
  1420.        
  1421.     }
  1422.  
  1423.  
  1424.   else if ((direction < G_PI) && (direction > G_PI_2))
  1425.  
  1426.     {
  1427.  
  1428.  
  1429.         masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2);
  1430.     misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2);
  1431.  
  1432.     ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist);
  1433.     mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist);
  1434.     
  1435.     iang = airblob->direction_abs - G_PI_2;
  1436.  
  1437.         airline->line[0].x = (xcenter - sin(iang + ma_angsupport) * masupport)/SUBSAMPLE;
  1438.     airline->line[0].y = (ycenter - cos(iang + ma_angsupport) * masupport)/SUBSAMPLE;
  1439.     airline->line[1].x = (xcenter + sin(iang + mi_angsupport) * misupport)/SUBSAMPLE;
  1440.     airline->line[1].y = (ycenter + cos(iang + mi_angsupport) * misupport)/SUBSAMPLE;
  1441.  
  1442.     airline->line[2].x = (xcenter - sin(iang) * airblob->main_line.size)/SUBSAMPLE;
  1443.     airline->line[2].y = (ycenter - cos(iang) * airblob->main_line.size)/SUBSAMPLE;
  1444.     airline->line[3].x = (xcenter + sin(iang) * airblob->minor_line.size)/SUBSAMPLE;
  1445.     airline->line[3].y = (ycenter + cos(iang) * airblob->minor_line.size)/SUBSAMPLE;
  1446.  
  1447.     airline->line[4].x = (xcenter - sin(iang - ma_angsupport) * masupport)/SUBSAMPLE;
  1448.     airline->line[4].y = (ycenter - cos(iang - ma_angsupport) * masupport)/SUBSAMPLE;
  1449.     airline->line[5].x = (xcenter + sin(iang - mi_angsupport) * misupport)/SUBSAMPLE;
  1450.     airline->line[5].y = (ycenter + cos(iang - mi_angsupport) * misupport)/SUBSAMPLE;
  1451.  
  1452.     /*airline->line[6].x = (xcenter - sin(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1453.     airline->line[6].y = (ycenter - cos(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1454.     airline->line[7].x = (xcenter - sin(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1455.     airline->line[7].y = (ycenter - cos(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1456.  
  1457.     airline->line[8].x = (xcenter - sin(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1458.     airline->line[8].y = (ycenter - cos(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1459.     airline->line[9].x = (xcenter - sin(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1460.     airline->line[9].y = (ycenter - cos(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1461.  
  1462.     airline->line[10].x = (xcenter - sin(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1463.     airline->line[10].y = (ycenter - cos(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1464.     airline->line[11].x = (xcenter - sin(iang - ma_angsupport/2. - ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1465.     airline->line[11].y = (ycenter - cos(iang - ma_angsupport/2. - ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;*/
  1466.     
  1467.     
  1468.     airline->nlines = 6;    
  1469.  
  1470.     }
  1471.  
  1472.   else if ((direction < G_PI_2) && (direction > 0.0))
  1473.  
  1474.     {
  1475.  
  1476.  
  1477.         masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2);
  1478.     misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2);
  1479.  
  1480.     ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist);
  1481.     mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist);
  1482.         
  1483.     iang = airblob->direction_abs;
  1484.  
  1485.         airline->line[0].x = (xcenter + cos(iang + ma_angsupport) * masupport)/SUBSAMPLE;
  1486.     airline->line[0].y = (ycenter - sin(iang + ma_angsupport) * masupport)/SUBSAMPLE;
  1487.     airline->line[1].x = (xcenter - cos(iang + mi_angsupport) * misupport)/SUBSAMPLE;
  1488.     airline->line[1].y = (ycenter + sin(iang + mi_angsupport) * misupport)/SUBSAMPLE;
  1489.  
  1490.     airline->line[2].x = (xcenter + cos(iang) * airblob->main_line.size)/SUBSAMPLE;
  1491.     airline->line[2].y = (ycenter - sin(iang) * airblob->main_line.size)/SUBSAMPLE;
  1492.     airline->line[3].x = (xcenter - cos(iang) * airblob->minor_line.size)/SUBSAMPLE;
  1493.     airline->line[3].y = (ycenter + sin(iang) * airblob->minor_line.size)/SUBSAMPLE;
  1494.  
  1495.     airline->line[4].x = (xcenter + cos(iang - ma_angsupport) * masupport)/SUBSAMPLE;
  1496.     airline->line[4].y = (ycenter - sin(iang - ma_angsupport) * masupport)/SUBSAMPLE;
  1497.     airline->line[5].x = (xcenter - cos(iang - mi_angsupport) * misupport)/SUBSAMPLE;
  1498.     airline->line[5].y = (ycenter + sin(iang - mi_angsupport) * misupport)/SUBSAMPLE;
  1499.     
  1500.  
  1501.     /*airline->line[6].x = (xcenter + cos(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1502.     airline->line[6].y = (ycenter - sin(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1503.     airline->line[7].x = (xcenter + cos(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1504.     airline->line[7].y = (ycenter - sin(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1505.  
  1506.     airline->line[8].x = (xcenter + cos(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1507.     airline->line[8].y = (ycenter - sin(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1508.     airline->line[9].x = (xcenter + cos(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1509.     airline->line[9].y = (ycenter - sin(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1510.  
  1511.     airline->line[10].x = (xcenter + cos(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1512.     airline->line[10].y = (ycenter - sin(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1513.     airline->line[11].x = (xcenter + cos(iang - ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1514.     airline->line[11].y = (ycenter - sin(iang - ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;
  1515.  
  1516.     airline->line[12].x = airline->line[2].x + (airline->line[4].x - airline->line[2].x)/4;
  1517.     airline->line[12].y = airline->line[2].y + (airline->line[4].y - airline->line[2].y)/4;
  1518.     airline->line[13].x = airline->line[2].x + 3 * (airline->line[4].x - airline->line[2].x)/4;
  1519.     airline->line[13].y = airline->line[2].y + 3 * (airline->line[4].y - airline->line[2].y)/4;
  1520.     */
  1521.  
  1522.  
  1523.  
  1524.     airline->nlines = 6;
  1525.  
  1526.        
  1527.     }
  1528.  
  1529.  
  1530.   else if ((direction < 0.0) && (direction > -G_PI_2))
  1531.  
  1532.     {
  1533.  
  1534.  
  1535.         masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2);
  1536.     misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2);
  1537.  
  1538.     ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist);
  1539.     mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist);
  1540.         
  1541.     iang = fabs(airblob->direction_abs);
  1542.  
  1543.         airline->line[0].x = (xcenter + cos(iang + ma_angsupport) * masupport)/SUBSAMPLE;
  1544.     airline->line[0].y = (ycenter + sin(iang + ma_angsupport) * masupport)/SUBSAMPLE;
  1545.     airline->line[1].x = (xcenter - cos(iang + mi_angsupport) * misupport)/SUBSAMPLE;
  1546.     airline->line[1].y = (ycenter - sin(iang + mi_angsupport) * misupport)/SUBSAMPLE;
  1547.  
  1548.     airline->line[2].x = (xcenter + cos(iang) * airblob->main_line.size)/SUBSAMPLE;
  1549.     airline->line[2].y = (ycenter + sin(iang) * airblob->main_line.size)/SUBSAMPLE;
  1550.     airline->line[3].x = (xcenter - cos(iang) * airblob->minor_line.size)/SUBSAMPLE;
  1551.     airline->line[3].y = (ycenter - sin(iang) * airblob->minor_line.size)/SUBSAMPLE;
  1552.  
  1553.     airline->line[4].x = (xcenter + cos(iang - ma_angsupport) * masupport)/SUBSAMPLE;
  1554.     airline->line[4].y = (ycenter + sin(iang - ma_angsupport) * masupport)/SUBSAMPLE;
  1555.     airline->line[5].x = (xcenter - cos(iang - mi_angsupport) * misupport)/SUBSAMPLE;
  1556.     airline->line[5].y = (ycenter - sin(iang - mi_angsupport) * misupport)/SUBSAMPLE;
  1557.     
  1558.     airline->nlines = 6;
  1559.        
  1560.     }
  1561.  
  1562.  
  1563.   else if ((direction < -G_PI_2) && (direction > -G_PI))
  1564.  
  1565.     {
  1566.  
  1567.  
  1568.         masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2);
  1569.     misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2);
  1570.     
  1571.     ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist);
  1572.     mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist);
  1573.     
  1574.     iang = fabs(airblob->direction_abs) - G_PI_2;
  1575.  
  1576.         airline->line[0].x = (xcenter - sin(iang + ma_angsupport) * masupport)/SUBSAMPLE;
  1577.     airline->line[0].y = (ycenter + cos(iang + ma_angsupport) * masupport)/SUBSAMPLE;
  1578.     airline->line[1].x = (xcenter + sin(iang + mi_angsupport) * misupport)/SUBSAMPLE;
  1579.     airline->line[1].y = (ycenter - cos(iang + mi_angsupport) * misupport)/SUBSAMPLE;
  1580.  
  1581.     airline->line[2].x = (xcenter - sin(iang) * airblob->main_line.size)/SUBSAMPLE;
  1582.     airline->line[2].y = (ycenter + cos(iang) * airblob->main_line.size)/SUBSAMPLE;
  1583.     airline->line[3].x = (xcenter + sin(iang) * airblob->minor_line.size)/SUBSAMPLE;
  1584.     airline->line[3].y = (ycenter - cos(iang) * airblob->minor_line.size)/SUBSAMPLE;
  1585.  
  1586.     airline->line[4].x = (xcenter - sin(iang - ma_angsupport) * masupport)/SUBSAMPLE;
  1587.     airline->line[4].y = (ycenter + cos(iang - ma_angsupport) * masupport)/SUBSAMPLE;
  1588.     airline->line[5].x = (xcenter + sin(iang - mi_angsupport) * misupport)/SUBSAMPLE;
  1589.     airline->line[5].y = (ycenter - cos(iang - mi_angsupport) * misupport)/SUBSAMPLE;
  1590.     
  1591.     airline->nlines = 6;
  1592.        
  1593.     }
  1594.  else
  1595.    {
  1596.      printf("Hmm a bug in the create_air_line");
  1597.    }
  1598.  
  1599.  
  1600.  
  1601.  
  1602.  
  1603.   min_x = max_x = airline->xcenter;
  1604.   min_y = max_y = airline->ycenter;
  1605.  
  1606.   /*
  1607.   
  1608.     for (i=0; i < airline->nlines ; i++)
  1609.     {
  1610.       printf("x%d, value %d\n", i, airline->line[i].x);
  1611.       printf("y%d, value %d\n", i, airline->line[i].y);
  1612.     }
  1613.  
  1614.   printf("The xcenter %d\n",airline->xcenter);  
  1615.   printf("The ycenter %d\n",airline->ycenter);
  1616.   
  1617.   */
  1618.  
  1619.   for (i=0; i < airline->nlines ; i++)
  1620.     {
  1621.        min_x = MIN(airline->line[i].x, min_x);
  1622.        max_x = MAX(airline->line[i].x, max_x);
  1623.        min_y = MIN(airline->line[i].y, min_y);
  1624.        max_y = MAX(airline->line[i].y, max_y);
  1625.     }
  1626.  
  1627.   airline->width = max_x - min_x + 1;
  1628.   airline->height = max_y - min_y + 1;
  1629.  
  1630.   airline->min_x = min_x;
  1631.   airline->min_y = min_y;
  1632.   airline->max_x = max_x;
  1633.   airline->max_y = max_y;
  1634.   
  1635.   return airline;
  1636.  
  1637. }
  1638.  
  1639. AirBlob *
  1640. trans_air_blob(AirBlob *airblob_last, AirBlob *airblob_present, double dist, int xcen, int ycen)
  1641. {
  1642.  
  1643.   AirBlob *trans_airblob;
  1644.  
  1645.   double direction_last_abs, direction_present_abs;
  1646.   double idirection_abs;
  1647.  
  1648.   double direction_last, direction_present;
  1649.   double idirection;
  1650.  
  1651.   double main_line_present, main_line_last;
  1652.  
  1653.  
  1654.   double minor_line_present, minor_line_last;
  1655.  
  1656.  
  1657.   double maincross_line_dist_present, maincross_line_dist_last;
  1658.  
  1659.   double minorcross_line_dist_present, minorcross_line_dist_last;
  1660.  
  1661.  
  1662.   double maincross_line_size_present, maincross_line_size_last;
  1663.  
  1664.   double minorcross_line_size_present, minorcross_line_size_last;
  1665.  
  1666.  
  1667.  
  1668.   trans_airblob = airblob_new(1);
  1669.  
  1670.   direction_last_abs = airblob_last->direction_abs + G_PI;
  1671.   direction_present_abs = airblob_present->direction_abs + G_PI;
  1672.  
  1673.   idirection_abs = direction_present_abs - direction_last_abs;
  1674.  
  1675.   direction_last = airblob_last->direction + G_PI_2;
  1676.   direction_present = airblob_present->direction + G_PI_2;
  1677.  
  1678.   idirection = direction_present - direction_last;
  1679.  
  1680.   main_line_present = airblob_present->main_line.size;
  1681.   main_line_last = airblob_last->main_line.size;
  1682.  
  1683.   minor_line_present = airblob_present->minor_line.size;
  1684.   minor_line_last = airblob_last->minor_line.size;
  1685.  
  1686.   maincross_line_dist_present = airblob_present->maincross_line.dist;
  1687.   maincross_line_size_present = airblob_present->maincross_line.size;  
  1688.   minorcross_line_dist_present = airblob_present->minorcross_line.dist;
  1689.   minorcross_line_size_present = airblob_present->minorcross_line.size;  
  1690.  
  1691.   maincross_line_dist_last = airblob_last->maincross_line.dist;
  1692.   maincross_line_size_last = airblob_last->maincross_line.size;  
  1693.   minorcross_line_dist_last = airblob_last->minorcross_line.dist;
  1694.   minorcross_line_size_last = airblob_last->minorcross_line.size;  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.   /* 
  1700.      Now we have to guess a little :-). Why? 
  1701.      Well we can't know if the users is painting
  1702.      up/down or if she is painting a circle at high speed.
  1703.      As you may notice it be so that the last airblob has 
  1704.      a direction more or less G_PI rad differernt from the
  1705.      present airblob. But we can't know if she tured the 
  1706.      airbrush quickly (so that there was no mouse capture 
  1707.      during the turn) or if she paints just up and down the
  1708.      same direction.
  1709.  
  1710.      There for we guess that we want to pait up and down 
  1711.      when the diff in direction is bigger than 171 deg and 
  1712.      smaller than 189 deg.
  1713.  
  1714.   */
  1715.  
  1716.   if ((fabs(idirection_abs) > (G_PI - 0.1571)) && (fabs(idirection_abs) < (G_PI + 0.1571)))
  1717.     {
  1718.       /* We asume that the artist meant to paint in a "strait line" by just tilting the airbrush*/
  1719.       
  1720.       idirection_abs = idirection_abs - G_PI;
  1721.      
  1722.       if ((idirection_abs * dist) > (idirection_abs/2))
  1723.     {
  1724.       if ((direction_present_abs - idirection_abs * dist) > 2 * G_PI)
  1725.         {
  1726.         trans_airblob->direction_abs = direction_present_abs - idirection_abs * dist - 2 * G_PI - G_PI;
  1727.         }
  1728.       else if ((direction_present_abs - idirection_abs * dist) < 0.0)
  1729.         {
  1730.           trans_airblob->direction_abs = direction_present_abs - idirection_abs * dist + 2 * G_PI - G_PI;
  1731.         }
  1732.       else 
  1733.         {
  1734.           trans_airblob->direction_abs = direction_present_abs - idirection_abs * dist - G_PI;
  1735.         }
  1736.     }
  1737.       else 
  1738.     {
  1739.       if ((direction_present_abs + idirection_abs * dist) > 2 * G_PI)
  1740.         {
  1741.         trans_airblob->direction_abs = direction_present_abs + idirection_abs * dist - 2 * G_PI - G_PI;
  1742.         }
  1743.       else if ((direction_present_abs + idirection_abs * dist) < 0.0)
  1744.         {
  1745.           trans_airblob->direction_abs = direction_present_abs + idirection_abs * dist + 2 * G_PI - G_PI;
  1746.         }
  1747.       else 
  1748.         {
  1749.           trans_airblob->direction_abs = direction_present_abs + idirection_abs * dist - G_PI;
  1750.         }
  1751.     }
  1752.  
  1753.       trans_airblob->main_line.size = main_line_last + ((minor_line_present - main_line_last) * dist); 
  1754.       trans_airblob->minor_line.size = minor_line_last + ((main_line_present - minor_line_last) * dist);
  1755.  
  1756.       trans_airblob->maincross_line.dist = maincross_line_dist_last + ((minorcross_line_dist_present - maincross_line_dist_last) * dist);
  1757.       trans_airblob->maincross_line.size = maincross_line_size_last + ((minorcross_line_size_present - maincross_line_size_last) * dist);
  1758.  
  1759.       trans_airblob->minorcross_line.dist = minorcross_line_dist_last + ((maincross_line_dist_present - minorcross_line_dist_last) * dist);
  1760.       trans_airblob->minorcross_line.size = minorcross_line_size_last + ((maincross_line_size_present - minorcross_line_size_last) * dist);
  1761.  
  1762.     }
  1763.   
  1764.   else if (fabs(idirection_abs) < (G_PI - 0.1571))
  1765.     {
  1766.       if ((direction_last_abs + idirection_abs * dist) > 2*G_PI)
  1767.     {
  1768.       trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - 2 * G_PI - G_PI;
  1769.     }
  1770.       else if((direction_last_abs + idirection_abs * dist) < 0.0)
  1771.     {
  1772.      trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist + 2 * G_PI - G_PI;
  1773.     } 
  1774.       else 
  1775.     {
  1776.       trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - G_PI;
  1777.     }
  1778.  
  1779.       trans_airblob->main_line.size = main_line_last + ((main_line_present - main_line_last) * dist); 
  1780.       trans_airblob->minor_line.size = minor_line_last + ((minor_line_present - minor_line_last) * dist);
  1781.  
  1782.       trans_airblob->maincross_line.dist = maincross_line_dist_last + ((maincross_line_dist_present - maincross_line_dist_last) * dist);
  1783.       trans_airblob->maincross_line.size = maincross_line_size_last + ((maincross_line_size_present - maincross_line_size_last) * dist);
  1784.  
  1785.       trans_airblob->minorcross_line.dist = minorcross_line_dist_last + ((minorcross_line_dist_present - minorcross_line_dist_last) * dist);
  1786.       trans_airblob->minorcross_line.size = minorcross_line_size_last + ((minorcross_line_size_present - minorcross_line_size_last) * dist);
  1787.     }
  1788.   else
  1789.     {
  1790.  
  1791.       /* We asume that the artist always travels the shortest way around the "clock" */
  1792.       
  1793.       idirection_abs = idirection_abs - G_PI;
  1794.  
  1795.       if ((direction_last_abs + idirection_abs * dist) > 2*G_PI)
  1796.     {
  1797.       trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - 2 * G_PI - G_PI;
  1798.     }
  1799.       else if((direction_last_abs + idirection_abs * dist) < 0.0)
  1800.     {
  1801.      trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist + 2 * G_PI - G_PI;
  1802.     } 
  1803.       else 
  1804.     {
  1805.       trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - G_PI;
  1806.     }
  1807.  
  1808.       trans_airblob->main_line.size = main_line_last + ((main_line_present - main_line_last) * dist); 
  1809.       trans_airblob->minor_line.size = minor_line_last + ((minor_line_present - minor_line_last) * dist);
  1810.  
  1811.       trans_airblob->maincross_line.dist = maincross_line_dist_last + ((maincross_line_dist_present - maincross_line_dist_last) * dist);
  1812.       trans_airblob->maincross_line.size = maincross_line_size_last + ((maincross_line_size_present - maincross_line_size_last) * dist);
  1813.  
  1814.       trans_airblob->minorcross_line.dist = minorcross_line_dist_last + ((minorcross_line_dist_present - minorcross_line_dist_last) * dist);
  1815.       trans_airblob->minorcross_line.size = minorcross_line_size_last + ((minorcross_line_size_present - minorcross_line_size_last) * dist);
  1816.  
  1817.     }
  1818.  
  1819.  
  1820.   trans_airblob->xcenter = xcen * SUBSAMPLE;
  1821.   trans_airblob->ycenter = ycen * SUBSAMPLE;
  1822.  
  1823.   return trans_airblob;
  1824.  
  1825. }
  1826.  
  1827.    
  1828.  
  1829.  
  1830.  
  1831.       
  1832.       
  1833.       
  1834.   
  1835.  
  1836.  
  1837.  
  1838.  
  1839.  
  1840.  
  1841.  
  1842.