libgeda

m_polygon.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * libgeda - gEDA's library
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 #include <config.h>
00021 #include <math.h>
00022 #include <string.h>
00023 #include <libgeda_priv.h>
00024 
00032 void m_polygon_append_bezier (GArray *points, BEZIER *bezier, int segments)
00033 {
00034   m_polygon_append_point (points, bezier->x[0], bezier->y[0]);
00035 
00036   if (segments > 1) {
00037     int i;
00038 
00039     double a = 3 / (double) segments;
00040     double b = 6 / pow (segments, 2);
00041     double c = 6 / pow (segments, 3);
00042 
00043     double x = bezier->x[0];
00044     double xd = a * (bezier->x[1] - bezier->x[0]);
00045     double xdd = b * (bezier->x[0] - 2 * bezier->x[1] + bezier->x[2]);
00046     double xddd = c * (3 * (bezier->x[1] - bezier->x[2]) + bezier->x[3] - bezier->x[0]);
00047 
00048     double xdd_div2 = xdd / 2;
00049     double xddd_div2 = xddd / 2;
00050     double xddd_div6 = xddd / 6;
00051 
00052     double y = bezier->y[0];
00053     double yd = a * (bezier->y[1] - bezier->y[0]);
00054     double ydd = b * (bezier->y[0] - 2 * bezier->y[1] + bezier->y[2]);
00055     double yddd = c * (3 * (bezier->y[1] - bezier->y[2]) + bezier->y[3] - bezier->y[0]);
00056 
00057     double ydd_div2 = ydd / 2;
00058     double yddd_div2 = yddd / 2;
00059     double yddd_div6 = yddd / 6;
00060 
00061     for (i=1; i < segments; i++) {
00062       x += xd + xdd_div2 + xddd_div6;
00063       xd += xdd + xddd_div2;
00064       xdd += xddd;
00065       xdd_div2 += xddd_div2;
00066 
00067       y += yd + ydd_div2 + yddd_div6;
00068       yd += ydd + yddd_div2;
00069       ydd += yddd;
00070       ydd_div2 += yddd_div2;
00071 
00072       m_polygon_append_point (points, round (x), round (y));
00073     }
00074   }
00075 
00076   m_polygon_append_point (points, bezier->x[3], bezier->y[3]);
00077 }
00078 
00086 void m_polygon_append_point (GArray *points, int x, int y)
00087 {
00088   sPOINT point = { x, y };
00089 
00090   point.x = x;
00091   point.y = y;
00092 
00093   if (points->len == 0 ||
00094       memcmp (&g_array_index (points, sPOINT, points->len - 1),
00095               &point, sizeof (sPOINT)) != 0) {
00096     g_array_append_val (points, point);
00097   }
00098 }
00099 
00113 gboolean m_polygon_interior_point (GArray *points, int x, int y)
00114 {
00115   int count = 0;
00116 
00117   if (points->len > 0) {
00118     int i;
00119     sPOINT p1 = g_array_index (points, sPOINT, points->len - 1);
00120 
00121     for (i=0; i < points->len; i++) {
00122       sPOINT p0 = p1;
00123       double xi;
00124 
00125       p1 = g_array_index (points, sPOINT, i);
00126 
00127       if (y < p0.y && y < p1.y)
00128         continue;
00129 
00130       if (y >= p0.y && y >= p1.y)
00131         continue;
00132 
00133       xi = ((double) (p1.x - p0.x)) * (y - p0.y) / (p1.y - p0.y) + p0.x;
00134 
00135       if (x < xi)
00136         count++;
00137     }
00138   }
00139   return (count % 2) == 1;  /* odd */
00140 }
00141 
00155 double m_polygon_shortest_distance (GArray *points, int x, int y, gboolean closed)
00156 {
00157   gdouble shortest = G_MAXDOUBLE;
00158 
00159   if (points->len > 0) {
00160     int i = 0;
00161     sPOINT point;
00162 
00163     if (closed) {
00164       point = g_array_index (points, sPOINT, points->len - 1);
00165     } else {
00166       point = g_array_index (points, sPOINT, i++);
00167     }
00168 
00169     while (i < points->len) {
00170       double distance;
00171       LINE line;
00172 
00173       line.x[0] = point.x;
00174       line.y[0] = point.y;
00175 
00176       point = g_array_index (points, sPOINT, i++);
00177 
00178       line.x[1] = point.x;
00179       line.y[1] = point.y;
00180 
00181       distance = m_line_shortest_distance (&line, x, y);
00182 
00183       shortest = min (shortest, distance);
00184     }
00185   }
00186 
00187   return shortest;
00188 }
00189 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines