#include "rays/ruby/polyline.h" #include #include #include "rays/ruby/color.h" #include "rays/ruby/point.h" #include "rays/ruby/bounds.h" #include "rays/ruby/polygon.h" #include "defs.h" RUCY_DEFINE_VALUE_OR_ARRAY_FROM_TO(RAYS_EXPORT, Rays::Polyline) #define THIS to(self) #define CHECK RUCY_CHECK_OBJECT(Rays::Polyline, self) static VALUE alloc(VALUE klass) { return new_type(klass); } static VALUE setup(VALUE self, VALUE points, VALUE loop, VALUE fill, VALUE colors, VALUE texcoords, VALUE hole) { CHECK; CreateParams params(points, colors, texcoords); *THIS = Rays::Polyline( params.ppoints(), params.size(), loop, fill, params.pcolors(), params.ptexcoords(), hole); } static VALUE expand(VALUE self) { CHECK; check_arg_count(__FILE__, __LINE__, "Polyline#expand", argc, 1, 2, 3, 4); coord width = to (argv[0]); Rays::CapType cap = argc >= 2 ? to (argv[1]) : Rays::CAP_DEFAULT; Rays::JoinType join = argc >= 3 ? to(argv[2]) : Rays::JOIN_DEFAULT; coord ml = argc >= 4 ? to (argv[3]) : (coord) Rays::JOIN_DEFAULT_MITER_LIMIT; Rays::Polygon polygon; THIS->expand(&polygon, width, cap, join, ml); return value(polygon); } static VALUE bounds(VALUE self) { CHECK; return value(THIS->bounds()); } static VALUE is_loop(VALUE self) { CHECK; return value(THIS->loop()); } static VALUE is_fill(VALUE self) { CHECK; return value(THIS->fill()); } static VALUE is_hole(VALUE self) { CHECK; return value(THIS->hole()); } static VALUE size(VALUE self) { CHECK; return value(THIS->size()); } static VALUE is_empty(VALUE self) { CHECK; return value(THIS->empty()); } static VALUE get_at(VALUE self, VALUE index) { CHECK; int size = (int) THIS->size(); int i = to(index); if (i < 0) i += size; if (i < 0) index_error(__FILE__, __LINE__); if (i >= size) index_error(__FILE__, __LINE__); return value((*THIS)[i]); } static VALUE has_points(VALUE self) { CHECK; return value(THIS->points() && !THIS->empty()); } static VALUE has_colors(VALUE self) { CHECK; return value(THIS->colors() && !THIS->empty()); } static VALUE has_texcoords(VALUE self) { CHECK; return value(THIS->texcoords() && !THIS->empty()); } static VALUE each_point(VALUE self) { CHECK; Value ret = Qnil; for (const auto& point : *THIS) ret = rb_yield(value(point)); return ret; } static VALUE each_color(VALUE self) { CHECK; const Rays::Color* colors = THIS->colors(); Value ret = Qnil; if (colors) { size_t size = THIS->size(); for (size_t i = 0; i < size; ++i) ret = rb_yield(value(colors[i])); } return ret; } static VALUE each_texcoord(VALUE self) { CHECK; const Rays::Coord3* texcoords = THIS->texcoords(); Value ret = Qnil; if (texcoords) { size_t size = THIS->size(); for (size_t i = 0; i < size; ++i) ret = rb_yield(value(*(Rays::Point*) &texcoords[i])); } return ret; } static Class cPolyline; void Init_rays_polyline () { Module mRays = rb_define_module("Rays"); cPolyline = rb_define_class_under(mRays, "Polyline", rb_cObject); rb_define_alloc_func(cPolyline, alloc); rb_define_private_method(cPolyline, "setup", RUBY_METHOD_FUNC(setup), 6); rb_define_method(cPolyline, "expand", RUBY_METHOD_FUNC(expand), -1); rb_define_method(cPolyline, "bounds", RUBY_METHOD_FUNC(bounds), 0); cPolyline.define_method("loop?", is_loop); cPolyline.define_method("fill?", is_fill); cPolyline.define_method("hole?", is_hole); rb_define_method(cPolyline, "size", RUBY_METHOD_FUNC(size), 0); cPolyline.define_method("empty?", is_empty); cPolyline.define_method("[]", get_at); cPolyline.define_method("points?", has_points); cPolyline.define_method("colors?", has_colors); cPolyline.define_method("texcoords?", has_texcoords); cPolyline.define_private_method("each_point!", each_point); cPolyline.define_private_method("each_color!", each_color); cPolyline.define_private_method("each_texcoord!", each_texcoord); } namespace Rucy { template <> RAYS_EXPORT Rays::Polyline value_to (int argc, const Value* argv, bool convert) { assert(argc == 0 || (argc > 0 && argv)); if (convert) { if (argc <= 0) return Rays::Polyline(); else if (argv->is_num() || argv->is_array()) { std::vector points; get_points(&points, argc, argv); return Rays::Polyline(&points[0], points.size()); } } if (argc != 1) argument_error(__FILE__, __LINE__); return value_to(*argv, convert); } }// Rucy namespace Rays { Class polyline_class () { return cPolyline; } }// Rays