46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# File 'ext/rbpip/rbpip.c', line 46
static VALUE c_contains_point(int argc, VALUE* argv, VALUE self) {
VALUE respond_to = rb_intern("respond_to?");
VALUE p_x;
VALUE p_y;
switch (argc) {
case 1: {
VALUE arg = argv[0];
VALUE responds_x = rb_funcall(arg, respond_to, 1, ID2SYM(rb_intern("x")));
VALUE responds_y = rb_funcall(arg, respond_to, 1, ID2SYM(rb_intern("y")));
if (responds_x == Qtrue && responds_y == Qtrue) {
p_x = rb_funcall(arg, rb_intern("x"), 0);
p_y = rb_funcall(arg, rb_intern("y"), 0);
} else {
rb_raise(rb_eArgError, "Argument must respond to :x and :y.");
}
break;
}
case 2: {
p_x = argv[0];
p_y = argv[1];
break;
}
default:
break;
}
Check_Type(p_x, T_FLOAT);
Check_Type(p_y, T_FLOAT);
VALUE polygon = Qnil;
switch (TYPE(self)) {
case T_ARRAY: {
polygon = self;
break;
}
case T_OBJECT: {
VALUE points_id = rb_intern("points");
VALUE responds = rb_funcall(self, respond_to, 1, ID2SYM(points_id));
if (responds == Qtrue) polygon = rb_funcall(self, points_id, 0);
else rb_raise(rb_eTypeError, "Receiver does not respond to :points.");
break;
}
default:
rb_raise(rb_eTypeError, "Receiver is not a valid polygon.");
break;
}
VALUE *poly_arr = RARRAY_PTR(polygon);
int poly_len = RARRAY_LEN(polygon);
if (poly_len < 3) rb_raise(rb_eTypeError, "Polygon must have at least 3 points");
double x = NUM2DBL(p_x);
double y = NUM2DBL(p_y);
//double *p_polygon = ALLOCA_N(double, 2 * poly_len);
double *p_polygon = (double *)malloc(sizeof(double)*2*poly_len);
for (int i = 0; i < poly_len; i++) {
Check_Type(poly_arr[i], T_ARRAY);
VALUE *p = RARRAY_PTR(poly_arr[i]);
int p_len = RARRAY_LEN(poly_arr[i]);
if (p_len != 2) rb_raise(rb_eTypeError, "A polygon's points must contain only two values.");
Check_Type(p[0], T_FLOAT);
Check_Type(p[1], T_FLOAT);
p_polygon[i*2] = NUM2DBL(p[0]);
p_polygon[(i*2)+1] = NUM2DBL(p[1]);
}
int res = pip((double (*)[2]) p_polygon, poly_len, x, y);
return res == 1 ? Qtrue : Qfalse;
}
|