class Object

Public Instance Methods

contains_point?(*args) click to toggle source
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);
    
    free(p_polygon);
    
    return res == 1 ? Qtrue : Qfalse;
}