Class: Object

Inherits:
BasicObject
Defined in:
(unknown)

Instance Method Summary collapse

Instance Method Details

#contains_point?(*args) ⇒ Boolean

Returns:

  • (Boolean)


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;
}