.doc/ext/rays/bounds.cpp in rays-0.1.6 vs .doc/ext/rays/bounds.cpp in rays-0.1.7

- old
+ new

@@ -1,74 +1,39 @@ #include "rays/ruby/bounds.h" #include <rucy.h> -#include <rays/ruby/point.h> +#include "rays/ruby/point.h" #include "defs.h" using namespace Rucy; using Rays::coord; static Class cBounds; +RUCY_DEFINE_VALUE_FROM_TO(Rays::Bounds, cBounds) -namespace Rays -{ +#define THIS to<Rays::Bounds*>(self) +#define CHECK RUCY_CHECK_OBJ(Rays::Bounds, cBounds, self) - Class - bounds_class () - { - return cBounds; - } - -}// Rays - - -namespace Rucy -{ - - - Value - value (const Rays::Bounds& obj) - { - return new_type(cBounds, new Rays::Bounds(obj)); - } - - Value - value (const Rays::Bounds* obj) - { - return obj ? value(*obj) : nil(); - } - - -}// Rucy - - -#define THIS to<Rays::Bounds*>(self) - -#define CHECK RUCY_CHECK_OBJ(self, Rays::Bounds, cBounds) - - static VALUE alloc(VALUE klass) { return new_type<Rays::Bounds>(klass); } static VALUE initialize(VALUE self) { - RUCY_CHECK_OBJ(self, Rays::Bounds, cBounds); + CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#initialize", argc, 0, 1, 2, 3, 4, 6); - if (argc != 0 && argc != 1 && argc != 2 && argc != 3 && argc != 4 && argc != 6) - arg_count_error("Bounds#initialize", argc, 0, 1, 2, 3, 4, 6); - if (argc == 0) return self; switch (argc) { case 1: @@ -101,20 +66,167 @@ } static VALUE initialize_copy(VALUE self, VALUE obj) { - RUCY_CHECK_OBJ(self, Rays::Bounds, cBounds); + CHECK; + *THIS = to<Rays::Bounds&>(obj); + return self; +} - Rays::Bounds* bounds = to<Rays::Bounds*>(obj); - if (!bounds) argument_error(); +static +VALUE intersect(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#intersect?", argc, 1, 2); - *THIS = *bounds; + const Rays::Bounds& bounds = to<Rays::Bounds&>(argv[0]); + int dimension = argc >= 2 ? to<int>(argv[1]) : 2; + + return value(THIS->is_intersect(bounds, dimension)); +} + +static +VALUE include(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#include?", argc, 1, 2); + + const Rays::Point& point = to<Rays::Point&>(argv[0]); + int dimension = argc >= 2 ? to<int>(argv[1]) : 2; + + return value(THIS->is_include(point, dimension)); +} + +static +VALUE move_to(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#move_to", argc, 1, 2, 3); + + if (argv[0].is_kind_of(Rays::point_class())) + THIS->move_to(to<Rays::Point&>(argv[0])); + else + { + if (argv[0].is_array()) + { + argc = argv[0].size(); + argv = argv[0].as_array(); + } + + const Rays::Point& p = THIS->position(); + coord x = (argc >= 1 && argv[0]) ? to<coord>(argv[0]) : p.x; + coord y = (argc >= 2 && argv[1]) ? to<coord>(argv[1]) : p.y; + coord z = (argc >= 3 && argv[2]) ? to<coord>(argv[2]) : p.z; + THIS->move_to(x, y, z); + } + return self; } static +VALUE move_by(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#move_by", argc, 1, 2, 3); + + if (argv[0].is_kind_of(Rays::point_class())) + THIS->move_by(to<Rays::Point&>(argv[0])); + else + { + if (argv[0].is_array()) + { + argc = argv[0].size(); + argv = argv[0].as_array(); + } + + coord x = (argc >= 1 && argv[0]) ? to<coord>(argv[0]) : 0; + coord y = (argc >= 2 && argv[1]) ? to<coord>(argv[1]) : 0; + coord z = (argc >= 3 && argv[2]) ? to<coord>(argv[2]) : 0; + THIS->move_by(x, y, z); + } + + return self; +} + +static +VALUE resize_to(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#resize_to", argc, 1, 2, 3); + + if (argv[0].is_kind_of(Rays::point_class())) + THIS->resize_to(to<Rays::Point&>(argv[0])); + else + { + if (argv[0].is_array()) + { + argc = argv[0].size(); + argv = argv[0].as_array(); + } + + const Rays::Point& p = THIS->size(); + coord x = (argc >= 1 && argv[0]) ? to<coord>(argv[0]) : p.x; + coord y = (argc >= 2 && argv[1]) ? to<coord>(argv[1]) : p.y; + coord z = (argc >= 3 && argv[2]) ? to<coord>(argv[2]) : p.z; + THIS->resize_to(x, y, z); + } + + return self; +} + +static +VALUE resize_by(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#resize_by", argc, 1, 2, 3); + + if (argv[0].is_kind_of(Rays::point_class())) + THIS->resize_by(to<Rays::Point&>(argv[0])); + else + { + if (argv[0].is_array()) + { + argc = argv[0].size(); + argv = argv[0].as_array(); + } + + coord x = (argc >= 1 && argv[0]) ? to<coord>(argv[0]) : 0; + coord y = (argc >= 2 && argv[1]) ? to<coord>(argv[1]) : 0; + coord z = (argc >= 3 && argv[2]) ? to<coord>(argv[2]) : 0; + THIS->resize_by(x, y, z); + } + + return self; +} + +static +VALUE inset_by(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#inset_by", argc, 1, 2, 3); + + if (argv[0].is_kind_of(Rays::point_class())) + THIS->inset_by(to<Rays::Point&>(argv[0])); + else + { + if (argv[0].is_array()) + { + argc = argv[0].size(); + argv = argv[0].as_array(); + } + + coord x = (argc >= 1 && argv[0]) ? to<coord>(argv[0]) : 0; + coord y = (argc >= 2 && argv[1]) ? to<coord>(argv[1]) : 0; + coord z = (argc >= 3 && argv[2]) ? to<coord>(argv[2]) : 0; + THIS->inset_by(x, y, z); + } + + return self; +} + +static VALUE set_x(VALUE self, VALUE x) { CHECK; return value(THIS->x = to<coord>(x)); @@ -315,18 +427,18 @@ return value(THIS->front()); } static -VALUE set_position(VALUE self, VALUE pos) +VALUE set_position(VALUE self) { CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#set_position", argc, 1, 2, 3); - Rays::Point* p = to<Rays::Point*>(pos); - if (!p) argument_error("%s is not a Rays::Point.", pos.inspect().c_str()); - - return value(THIS->position() = *p); + coord* pos = THIS->position().array; + for (int i = 0; i < 3; ++i) + if (argc > i && !argv[i].is_nil()) pos[i] = to<coord>(argv[i]); } static VALUE get_position(VALUE self) { @@ -334,38 +446,126 @@ return value(THIS->position()); } static -VALUE set_size(VALUE self, VALUE size) +VALUE set_size(VALUE self) { CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#set_size", argc, 1, 2, 3); - Rays::Point* p = to<Rays::Point*>(size); - if (!p) argument_error("%s is not a Rays::Point.", size.inspect().c_str()); - - return value(THIS->size() = *p); + coord* size = THIS->size().array; + for (int i = 0; i < 3; ++i) + if (argc > i && !argv[i].is_nil()) size[i] = to<coord>(argv[i]); } static VALUE get_size(VALUE self) { CHECK; return value(THIS->size()); } +static +VALUE set_center(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Bounds#set_center", argc, 1, 2, 3); + if (argv[0].is_kind_of(Rays::point_class())) + THIS->set_center(to<Rays::Point&>(argv[0])); + else + { + Rays::Point p = THIS->center(); + coord x = (argc >= 1 && argv[0]) ? to<coord>(argv[0]) : p.x; + coord y = (argc >= 2 && argv[1]) ? to<coord>(argv[1]) : p.y; + coord z = (argc >= 3 && argv[2]) ? to<coord>(argv[2]) : p.z; + THIS->set_center(x, y, z); + } + + return value(THIS->center()); +} + +static +VALUE center(VALUE self) +{ + CHECK; + + return value(THIS->center()); +} + +static +VALUE array_get(VALUE self, VALUE index) +{ + CHECK; + + int i = index.as_i(); + if (i < 0 || 1 < i) + index_error(__FILE__, __LINE__); + + return value((*THIS)[i]); +} + +static +VALUE array_set(VALUE self, VALUE index, VALUE value) +{ + CHECK; + + int i = index.as_i(); + if (i < 0 || 1 < i) + index_error(__FILE__, __LINE__); + + (*THIS)[i] = to<Rays::Point&>(value); + return value; +} + +static +VALUE and_(VALUE self, VALUE bounds) +{ + CHECK; + + Rays::Bounds b = *THIS; + b &= to<Rays::Bounds&>(bounds); + return value(b); +} + +static +VALUE or_(VALUE self, VALUE bounds) +{ + CHECK; + + Rays::Bounds b = *THIS; + b |= to<Rays::Bounds&>(bounds); + return value(b); +} + +static +VALUE inspect(VALUE self) +{ + CHECK; + + return value(Xot::stringf("#<Rays::Bounds %s>", THIS->inspect().c_str())); +} + + void Init_bounds () { Module mRays = rb_define_module("Rays"); cBounds = rb_define_class_under(mRays, "Bounds", rb_cObject); rb_define_alloc_func(cBounds, alloc); rb_define_private_method(cBounds, "initialize", RUBY_METHOD_FUNC(initialize), -1); rb_define_private_method(cBounds, "initialize_copy", RUBY_METHOD_FUNC(initialize_copy), 1); + cBounds.define_method("intersect?", intersect); + cBounds.define_method("include?", include); + cBounds.define_method("move_to!", move_to); + cBounds.define_method("move_by!", move_by); + cBounds.define_method("resize_to!", resize_to); + cBounds.define_method("resize_by!", resize_by); + cBounds.define_method("inset_by!", inset_by); rb_define_method(cBounds, "x=", RUBY_METHOD_FUNC(set_x), 1); rb_define_method(cBounds, "x", RUBY_METHOD_FUNC(get_x), 0); rb_define_method(cBounds, "y=", RUBY_METHOD_FUNC(set_y), 1); rb_define_method(cBounds, "y", RUBY_METHOD_FUNC(get_y), 0); rb_define_method(cBounds, "z=", RUBY_METHOD_FUNC(set_z), 1); @@ -386,10 +586,92 @@ rb_define_method(cBounds, "bottom", RUBY_METHOD_FUNC(get_bottom), 0); rb_define_method(cBounds, "back=", RUBY_METHOD_FUNC(set_back), 1); rb_define_method(cBounds, "back", RUBY_METHOD_FUNC(get_back), 0); rb_define_method(cBounds, "front=", RUBY_METHOD_FUNC(set_front), 1); rb_define_method(cBounds, "front", RUBY_METHOD_FUNC(get_front), 0); - rb_define_method(cBounds, "position=", RUBY_METHOD_FUNC(set_position), 1); + rb_define_method(cBounds, "set_position", RUBY_METHOD_FUNC(set_position), -1); rb_define_method(cBounds, "position", RUBY_METHOD_FUNC(get_position), 0); - rb_define_method(cBounds, "size=", RUBY_METHOD_FUNC(set_size), 1); + rb_define_method(cBounds, "set_size", RUBY_METHOD_FUNC(set_size), -1); rb_define_method(cBounds, "size", RUBY_METHOD_FUNC(get_size), 0); + rb_define_method(cBounds, "set_center", RUBY_METHOD_FUNC(set_center), -1); + rb_define_method(cBounds, "center", RUBY_METHOD_FUNC(center), 0); + cBounds.define_method("[]", array_get); + cBounds.define_method("[]=", array_set); + cBounds.define_method("&", and_); + cBounds.define_method("|", or_); + rb_define_method(cBounds, "inspect", RUBY_METHOD_FUNC(inspect), 0); } + + +namespace Rucy +{ + + + template <> Rays::Bounds + value_to<Rays::Bounds> (Value value, bool convert) + { + if (convert) + { + size_t argc = 0; + Value* argv = NULL; + if (value.is_array()) + { + argc = value.size(); + argv = value.as_array(); + } + else + { + argc = 1; + argv = &value; + } + + if (argc < 1) + Rucy::argument_error(__FILE__, __LINE__); + + if (argv[0].is_kind_of(Rays::bounds_class())) + value = argv[0]; + else if (argv[0].is_kind_of(Rays::point_class())) + { + switch (argc) + { + #define V(i) to<Rays::Point&>(argv[i]) + case 1: return Rays::Bounds(V(0)); + case 2: return Rays::Bounds(V(0), V(1)); + #undef V + default: Rucy::argument_error(__FILE__, __LINE__); + } + } + else if (argv[0].is_i() || argv[0].is_f()) + { + switch (argc) + { + #define V(i) argv[i].as_f(true) + case 1: return Rays::Bounds(V(0)); + case 2: return Rays::Bounds(V(0), V(1)); + case 3: return Rays::Bounds(V(0), V(1), V(2)); + case 4: return Rays::Bounds(V(0), V(1), V(2), V(3)); + case 6: return Rays::Bounds(V(0), V(1), V(2), V(3), V(4), V(5)); + #undef V + default: Rucy::argument_error(__FILE__, __LINE__); + } + } + } + + return value_to<Rays::Bounds&>(value, convert); + } + + +}// Rucy + + +namespace Rays +{ + + + Class + bounds_class () + { + return cBounds; + } + + +}// Rays