libgeda
|
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