SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
pointInsideContour.c
Go to the documentation of this file.
1/**
2 * @file pointInsideContour.c
3 * @brief Provides functions for determining the relative position of points
4 * with respect to a polygonal contour, including whether a point lies inside it.
5 *
6 * @copyright
7 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
8 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
9 *
10 * @license
11 * This file is distributed under the terms of the Software License Agreement
12 * found in the file LICENSE included with this distribution.
13 *
14 * @author M. Borland, R. Soliday
15 */
16/* This code found on multiple internet sources, translated to C */
17#include "mdb.h"
18
19double pointIsLeftOfLine(int64_t i1, int64_t i2, /* indices of vertex points to test */
20 double *x, double *y, /* (x, y) of vertices */
21 double x0, double y0 /* (x, y) of point to test */
22) {
23 double result;
24 result = (x[i2] - x[i1]) * (y0 - y[i1]) - (x0 - x[i1]) * (y[i2] - y[i1]);
25#ifdef DEBUG
26 printf("pointIsLeftOfLine(%ld, %ld, %le, %le) = %le\n",
27 i1, i2, x0, y0, result);
28 fflush(stdout);
29#endif
30
31 return result;
32}
33
34/**
35 * @brief Determine if a given point (x0, y0) is inside a specified polygonal contour.
36 *
37 * This function uses the winding number method to check if the point (x0, y0)
38 * is inside the polygon defined by arrays x and y. If a rotation is specified
39 * (by a non-zero theta and a center), the point is rotated about the given center
40 * before the inside test is performed.
41 *
42 * @param[in] x0 The x-coordinate of the point to test.
43 * @param[in] y0 The y-coordinate of the point to test.
44 * @param[in] x Array of x-coordinates of the polygon vertices.
45 * @param[in] y Array of y-coordinates of the polygon vertices.
46 * @param[in] n The number of vertices in the polygon.
47 * @param[in] center Pointer to an array representing the (x,y) center of rotation.
48 * @param[in] theta The clockwise rotation angle (in radians) to apply to the polygon.
49 * @return Non-zero if the point is inside the polygon, zero otherwise.
50 */
52 double x0, double y0, /* point to check */
53 double *x, double *y, /* points on contour */
54 int64_t n, /* points in contour */
55 double *center, /* center of rotation of contour */
56 double theta /* clockwise angle to rotation of contour */
57) {
58 int64_t winding_number = 0;
59 int64_t i1, i2;
60
61 if (theta != 0 && center) {
62 double x1, y1, ct, st;
63 /* rotate (x0, y0) by theta about center */
64 x0 -= center[0];
65 y0 -= center[1];
66 ct = cos(theta);
67 st = sin(theta);
68 x1 = x0 * ct - y0 * st + center[0];
69 y1 = x0 * st + y0 * ct + center[1];
70 x0 = x1;
71 y0 = y1;
72 }
73
74 for (i1 = 0; i1 < n; i1++) {
75 if (i1 == (n - 1))
76 /* wrap */
77 i2 = 0;
78 else
79 i2 = i1 + 1;
80
81 if (y[i1] <= y0) {
82 /* start y <= y0 */
83 if (y[i2] > y0) {
84 /* upward crossing */
85#ifdef DEBUG
86 printf("upward crossing\n");
87 fflush(stdout);
88#endif
89 if (pointIsLeftOfLine(i1, i2, x, y, x0, y0) > 0) {
90 /* Point left of edge */
91 ++winding_number;
92 }
93 }
94 } else {
95 /* start y > y0 */
96 if (y[i2] <= y0) {
97 /* downward crossing */
98#ifdef DEBUG
99 printf("downward crossing\n");
100 fflush(stdout);
101#endif
102 if (pointIsLeftOfLine(i1, i2, x, y, x0, y0) < 0) {
103 /* Point right of edge */
104 --winding_number;
105 }
106 }
107 }
108#ifdef DEBUG
109 printf("i1 = %" PRId64 ", winding_number = %" PRId64 "\n", i1, winding_number);
110 fflush(stdout);
111#endif
112 }
113
114#ifdef DEBUG
115 printf("winding_number = %" PRId64 "\n", winding_number);
116 fflush(stdout);
117#endif
118
119 return (winding_number != 0);
120}
121
int pointIsInsideContour(double x0, double y0, double *x, double *y, int64_t n, double *center, double theta)
Determine if a given point (x0, y0) is inside a specified polygonal contour.