1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <libgeda_priv.h>
25 /*! \brief Appends a bezier curve to the polygon
27 * \param points [inout] The vertices of the polygon. This parameter must not
29 * \param bezier [in] The bezier curve to append.
30 * \param segments [in] The number of segments to subdivide the bezier curve into.
32 void m_polygon_append_bezier (GArray
*points
, BEZIER
*bezier
, int segments
)
34 m_polygon_append_point (points
, bezier
->x
[0], bezier
->y
[0]);
39 double a
= 3 / (double) segments
;
40 double b
= 6 / pow (segments
, 2);
41 double c
= 6 / pow (segments
, 3);
43 double x
= bezier
->x
[0];
44 double xd
= a
* (bezier
->x
[1] - bezier
->x
[0]);
45 double xdd
= b
* (bezier
->x
[0] - 2 * bezier
->x
[1] + bezier
->x
[2]);
46 double xddd
= c
* (3 * (bezier
->x
[1] - bezier
->x
[2]) + bezier
->x
[3] - bezier
->x
[0]);
48 double xdd_div2
= xdd
/ 2;
49 double xddd_div2
= xddd
/ 2;
50 double xddd_div6
= xddd
/ 6;
52 double y
= bezier
->y
[0];
53 double yd
= a
* (bezier
->y
[1] - bezier
->y
[0]);
54 double ydd
= b
* (bezier
->y
[0] - 2 * bezier
->y
[1] + bezier
->y
[2]);
55 double yddd
= c
* (3 * (bezier
->y
[1] - bezier
->y
[2]) + bezier
->y
[3] - bezier
->y
[0]);
57 double ydd_div2
= ydd
/ 2;
58 double yddd_div2
= yddd
/ 2;
59 double yddd_div6
= yddd
/ 6;
61 for (i
=1; i
< segments
; i
++) {
62 x
+= xd
+ xdd_div2
+ xddd_div6
;
63 xd
+= xdd
+ xddd_div2
;
65 xdd_div2
+= xddd_div2
;
67 y
+= yd
+ ydd_div2
+ yddd_div6
;
68 yd
+= ydd
+ yddd_div2
;
70 ydd_div2
+= yddd_div2
;
72 m_polygon_append_point (points
, round (x
), round (y
));
76 m_polygon_append_point (points
, bezier
->x
[3], bezier
->y
[3]);
79 /*! \brief Appends a point to the list of vertices in a polygon
81 * \param points [inout] The vertices of the polygon. This parameter must not
83 * \param x [in] The x coordinate of the point to append.
84 * \param y [in] The y coordinate of the point to append.
86 void m_polygon_append_point (GArray
*points
, int x
, int y
)
88 sPOINT point
= { x
, y
};
93 if (points
->len
== 0 ||
94 memcmp (&g_array_index (points
, sPOINT
, points
->len
- 1),
95 &point
, sizeof (sPOINT
)) != 0) {
96 g_array_append_val (points
, point
);
100 /*! \brief Determines if a point lies inside a polygon
104 * \param points [in] The vertices of the polygon. This function assumes the
105 * list of points represents a closed polygon. If the first and last point do
106 * not match, the line segment between them is implied. This parameter must
108 * \param x [in] The x coordinate of the given point.
109 * \param y [in] The y coordinate of the given point.
110 * \returns TRUE if the point lies inside the polygon, FALSE if the point lies
111 * outside the polygon.
113 gboolean
m_polygon_interior_point (GArray
*points
, int x
, int y
)
117 if (points
->len
> 0) {
119 sPOINT p1
= g_array_index (points
, sPOINT
, points
->len
- 1);
121 for (i
=0; i
< points
->len
; i
++) {
125 p1
= g_array_index (points
, sPOINT
, i
);
127 if (y
< p0
.y
&& y
< p1
.y
)
130 if (y
>= p0
.y
&& y
>= p1
.y
)
133 xi
= ((double) (p1
.x
- p0
.x
)) * (y
- p0
.y
) / (p1
.y
- p0
.y
) + p0
.x
;
139 return (count
% 2) == 1; /* odd */
142 /*! \brief Calculates the distance between the given point and the closest
143 * point on the perimeter of the polygon.
145 * \param [in] points The polygon, where polygon != NULL.
146 * \param [in] x The x coordinate of the given point.
147 * \param [in] y The y coordinate of the given point.
148 * \param [in] closed If TRUE, the function treats the polygon as a closed
149 * shape, creating a line between the first and last points, if needed. If
150 * the first and last points are equal, or inherintly closed, this parameter
152 * \return The shortest distance from the polygon to the point. With an
153 * invalid parameter, this function returns G_MAXDOUBLE.
155 double m_polygon_shortest_distance (GArray
*points
, int x
, int y
, gboolean closed
)
157 gdouble shortest
= G_MAXDOUBLE
;
159 if (points
->len
> 0) {
164 point
= g_array_index (points
, sPOINT
, points
->len
- 1);
166 point
= g_array_index (points
, sPOINT
, i
++);
169 while (i
< points
->len
) {
176 point
= g_array_index (points
, sPOINT
, i
++);
181 distance
= m_line_shortest_distance (&line
, x
, y
);
183 shortest
= min (shortest
, distance
);