globegit-postgresql-plruby 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. data/Changes +121 -0
  2. data/README.markdown +155 -0
  3. data/Rakefile +48 -0
  4. data/docs/plruby.rb +1931 -0
  5. data/ex_trans.sql +33 -0
  6. data/extconf.rb +267 -0
  7. data/plruby.html +1454 -0
  8. data/plruby.rd +1571 -0
  9. data/postgresql-plruby.gemspec +56 -0
  10. data/src/conversions.h +5 -0
  11. data/src/conversions/basic/conversions.h +25 -0
  12. data/src/conversions/basic/extconf.rb +8 -0
  13. data/src/conversions/basic/plruby_basic.c +357 -0
  14. data/src/conversions/bitstring/bitstring.sql +75 -0
  15. data/src/conversions/bitstring/conversions.h +15 -0
  16. data/src/conversions/bitstring/extconf.rb +8 -0
  17. data/src/conversions/bitstring/plruby_bitstring.c +579 -0
  18. data/src/conversions/convcommon.h +129 -0
  19. data/src/conversions/datetime/conversions.h +13 -0
  20. data/src/conversions/datetime/extconf.rb +8 -0
  21. data/src/conversions/datetime/plruby_datetime.c +269 -0
  22. data/src/conversions/geometry/conversions.h +37 -0
  23. data/src/conversions/geometry/extconf.rb +8 -0
  24. data/src/conversions/geometry/geometry.sql +196 -0
  25. data/src/conversions/geometry/plruby_geometry.c +2494 -0
  26. data/src/conversions/network/conversions.h +21 -0
  27. data/src/conversions/network/extconf.rb +8 -0
  28. data/src/conversions/network/network.sql +63 -0
  29. data/src/conversions/network/plruby_network.c +537 -0
  30. data/src/package.h +20 -0
  31. data/src/plpl.c +1708 -0
  32. data/src/plplan.c +893 -0
  33. data/src/plruby.c +1676 -0
  34. data/src/plruby.h +324 -0
  35. data/src/pltrans.c +388 -0
  36. data/test/conv_bitstring/b.rb +45 -0
  37. data/test/conv_bitstring/runtest +26 -0
  38. data/test/conv_bitstring/test.expected.73 +148 -0
  39. data/test/conv_bitstring/test.expected.74 +148 -0
  40. data/test/conv_bitstring/test.expected.80 +148 -0
  41. data/test/conv_bitstring/test.expected.81 +148 -0
  42. data/test/conv_bitstring/test.expected.82 +148 -0
  43. data/test/conv_bitstring/test.expected.83 +148 -0
  44. data/test/conv_bitstring/test.expected.84 +148 -0
  45. data/test/conv_bitstring/test.out +148 -0
  46. data/test/conv_bitstring/test_mklang.sql +8 -0
  47. data/test/conv_bitstring/test_queries.sql +63 -0
  48. data/test/conv_bitstring/test_queries.sql.in +63 -0
  49. data/test/conv_geometry/b.rb +45 -0
  50. data/test/conv_geometry/runtest +26 -0
  51. data/test/conv_geometry/test.expected.73 +265 -0
  52. data/test/conv_geometry/test.expected.74 +265 -0
  53. data/test/conv_geometry/test.expected.80 +265 -0
  54. data/test/conv_geometry/test.expected.81 +265 -0
  55. data/test/conv_geometry/test.expected.82 +265 -0
  56. data/test/conv_geometry/test.expected.83 +265 -0
  57. data/test/conv_geometry/test.expected.84 +265 -0
  58. data/test/conv_geometry/test.out +265 -0
  59. data/test/conv_geometry/test_mklang.sql +8 -0
  60. data/test/conv_geometry/test_queries.sql +194 -0
  61. data/test/conv_geometry/test_queries.sql.in +194 -0
  62. data/test/conv_network/b.rb +45 -0
  63. data/test/conv_network/runtest +26 -0
  64. data/test/conv_network/test.expected.73 +213 -0
  65. data/test/conv_network/test.expected.74 +237 -0
  66. data/test/conv_network/test.expected.80 +237 -0
  67. data/test/conv_network/test.expected.81 +237 -0
  68. data/test/conv_network/test.expected.82 +237 -0
  69. data/test/conv_network/test.expected.83 +237 -0
  70. data/test/conv_network/test.expected.84 +237 -0
  71. data/test/conv_network/test.out +237 -0
  72. data/test/conv_network/test_mklang.sql +8 -0
  73. data/test/conv_network/test_queries.sql +60 -0
  74. data/test/conv_network/test_queries.sql.in +60 -0
  75. data/test/plp/b.rb +34 -0
  76. data/test/plp/runtest +29 -0
  77. data/test/plp/test.expected.73 +472 -0
  78. data/test/plp/test.expected.74 +472 -0
  79. data/test/plp/test.expected.75 +472 -0
  80. data/test/plp/test.expected.80 +472 -0
  81. data/test/plp/test.expected.81 +472 -0
  82. data/test/plp/test.expected.82 +472 -0
  83. data/test/plp/test.expected.83 +472 -0
  84. data/test/plp/test.expected.84 +472 -0
  85. data/test/plp/test.out +472 -0
  86. data/test/plp/test_mklang.sql +8 -0
  87. data/test/plp/test_queries.sql +273 -0
  88. data/test/plp/test_setup.sql +931 -0
  89. data/test/plp/test_setup.sql.in +931 -0
  90. data/test/plt/b.rb +34 -0
  91. data/test/plt/runtest +29 -0
  92. data/test/plt/test.expected.73 +178 -0
  93. data/test/plt/test.expected.74 +178 -0
  94. data/test/plt/test.expected.75 +178 -0
  95. data/test/plt/test.expected.80 +178 -0
  96. data/test/plt/test.expected.81 +178 -0
  97. data/test/plt/test.expected.82 +178 -0
  98. data/test/plt/test.expected.83 +164 -0
  99. data/test/plt/test.expected.84 +168 -0
  100. data/test/plt/test.out +168 -0
  101. data/test/plt/test_mklang.sql +8 -0
  102. data/test/plt/test_queries.sql +72 -0
  103. data/test/plt/test_setup.sql +252 -0
  104. data/test/plt/test_setup.sql.in +252 -0
  105. data/test/range/b.rb +45 -0
  106. data/test/range/runtest +26 -0
  107. data/test/range/test.expected.73 +396 -0
  108. data/test/range/test.expected.73.in +396 -0
  109. data/test/range/test.expected.74 +396 -0
  110. data/test/range/test.expected.74.in +396 -0
  111. data/test/range/test.expected.75 +396 -0
  112. data/test/range/test.expected.75.in +396 -0
  113. data/test/range/test.expected.80 +396 -0
  114. data/test/range/test.expected.81 +397 -0
  115. data/test/range/test.expected.82 +397 -0
  116. data/test/range/test.expected.83 +397 -0
  117. data/test/range/test.expected.84 +399 -0
  118. data/test/range/test.out +399 -0
  119. data/test/range/test_mklang.sql +8 -0
  120. data/test/range/test_queries.sql +249 -0
  121. data/test/range/test_queries.sql.in +249 -0
  122. metadata +207 -0
@@ -0,0 +1,8 @@
1
+ require 'mkmf'
2
+
3
+ if CONFIG["LIBRUBYARG"] == "$(LIBRUBYARG_SHARED)" &&
4
+ !enable_config("plruby-shared")
5
+ $LIBRUBYARG = ""
6
+ end
7
+ have_library('ruby18', 'ruby_init')
8
+ create_makefile('plruby/plruby_geometry')
@@ -0,0 +1,196 @@
1
+ set client_min_messages = 'WARNING';
2
+
3
+ drop table pl_box cascade;
4
+
5
+ create table pl_box (
6
+ data box, barea float, boverlaps bool, boverleft bool, boverright bool,
7
+ bleft bool, bright bool
8
+ );
9
+
10
+ create or replace function box_val(box[]) returns setof pl_box as '
11
+ b1 = Box.new(2.5,2.5,1.0,1.0)
12
+ b2 = Box.new(2.0,2.0,2.5,2.5)
13
+ b3 = Box.new(3.0,3.0,5.0,5.0)
14
+ args[0].each do |b|
15
+ yield [b, b.area, b.overlap?(b1), b.overleft?(b2),
16
+ b.overright?(b2), b.left?(b3), b3.right?(b)]
17
+ end
18
+ ' language 'plruby';
19
+
20
+ select * from
21
+ box_val('{(2.0,2.0,0.0,0.0);(1.0,1.0,3.0,3.0);(2.5,2.5,2.5,3.5);(3.0,3.0,3.0,3.0)'::box[]);
22
+
23
+ drop table pl_box cascade;
24
+
25
+ create table pl_box (
26
+ b box, bcmp1 int, bcmp2 int, bin bool, bcontain bool, bcenter point
27
+ );
28
+
29
+ create or replace function box_val(box[]) returns setof pl_box as '
30
+ b1 = Box.new(3.0,3.0,5.0,5.0)
31
+ b2 = Box.new(3.5,3.0,4.5,3.0)
32
+ b3 = Box.new(0,0,3,3)
33
+ args[0].each do |b|
34
+ yield [b, b <=> b1, b <=> b2, b.in?(b3), b.contain?(b3), b.center]
35
+ end
36
+ ' language 'plruby';
37
+
38
+ select * from
39
+ box_val('{(2.0,2.0,0.0,0.0);(1.0,1.0,3.0,3.0);(2.5,2.5,2.5,3.5);(3.0,3.0,3.0,3.0)}'::box[]);
40
+
41
+ drop table pl_box cascade;
42
+
43
+ create table pl_box (
44
+ b0 box, b1 box, b2 box, b3 box
45
+ );
46
+
47
+ create or replace function box_val(box[]) returns setof pl_box as '
48
+ p0 = [Point.new(-10.0,0.0), Point.new(-3.0,4.0),
49
+ Point.new(5.1, 34.5), Point.new(-5.0,-12.0)]
50
+ args[0].each do |b|
51
+ p0.each do |p|
52
+ yield [b + p, b - p, b * p, b / p]
53
+ end
54
+ p0.each do |p|
55
+ yield [p + b, p - b, p * b, p / b]
56
+ end
57
+ end
58
+ ' language 'plruby';
59
+
60
+ select * from
61
+ box_val('{(2.0,2.0,0.0,0.0);(1.0,1.0,3.0,3.0);(2.5,2.5,2.5,3.5);(3.0,3.0,3.0,3.0)}'::box[]);
62
+
63
+ drop table pl_box cascade;
64
+
65
+ create table pl_box (
66
+ p point, dp float, d0 float, c circle, w float, h float
67
+ );
68
+
69
+ create or replace function box_val(box[]) returns setof pl_box as '
70
+ p = Point.new(6,4)
71
+ args[0].each do |b|
72
+ p0 = b.center
73
+ yield [p0, Geometry::distance(p, b),Geometry::distance(p, p0),
74
+ b.to_circle, b.height, b.width]
75
+ end
76
+ ' language 'plruby';
77
+
78
+ select * from
79
+ box_val('{(2.0,2.0,0.0,0.0);(1.0,1.0,3.0,3.0);(2.5,2.5,2.5,3.5);(3.0,3.0,3.0,3.0)}'::box[]);
80
+
81
+ drop table pl_box cascade;
82
+
83
+ create table pl_box (
84
+ nb int, ll float, pc bool
85
+ );
86
+
87
+ create or replace function path_val(path[]) returns setof pl_box as '
88
+ args[0].each do |b|
89
+ yield [b.npoints, b.length, b.closed?]
90
+ end
91
+ ' language 'plruby';
92
+
93
+ select * from
94
+ path_val('{[1,2,3,4],(0,0),(3,0),(4,5),(1,6),11,12,13,14,25,12}'::path[]);
95
+
96
+ drop table pl_box cascade;
97
+
98
+ create table pl_box (
99
+ p path, p0 path, p1 path
100
+ );
101
+
102
+ create or replace function path_val(path[]) returns setof pl_box as '
103
+ p0 = Point.new(6,7)
104
+ args[0].each do |b|
105
+ yield [b, b + p0, b - p0]
106
+ end
107
+ ' language 'plruby';
108
+
109
+ select * from
110
+ path_val('{"[1,2,3,4]","(0,0),(3,0),(4,5),(1,6)","11,12,13,14,25,12"}'::path[]);
111
+
112
+ drop table pl_box cascade;
113
+
114
+ create table pl_box (
115
+ p path, p0 path, p1 path
116
+ );
117
+
118
+ create or replace function path_val(path[]) returns setof pl_box as '
119
+ p0 = Point.new(6,7)
120
+ args[0].each do |b|
121
+ yield [b, b * p0, b / p0]
122
+ end
123
+ ' language 'plruby';
124
+
125
+ select * from
126
+ path_val('{"[1,2,3,4]","(0,0),(3,0),(4,5),(1,6)","11,12,13,14,25,12"}'::path[]);
127
+
128
+ drop table pl_box cascade;
129
+
130
+ create table pl_box (
131
+ center point, area float, radius float, diameter float
132
+ );
133
+
134
+ create or replace function circle_val(circle[]) returns setof pl_box as '
135
+ args[0].each do |b|
136
+ yield b.center, b.area, b.radius, b.diameter
137
+ end
138
+ ' language 'plruby';
139
+
140
+ select * from
141
+ circle_val('{"<(5,1),3>","<(1,2),100>","<(100,200),10>","<(100,1),115>","1,3,5"}'::circle[]);
142
+
143
+
144
+ drop table pl_box cascade;
145
+
146
+ create table pl_box (
147
+ p circle, p0 circle, p1 circle
148
+ );
149
+
150
+ create or replace function circle_val(circle[]) returns setof pl_box as '
151
+ p0 = Point.new(6,7)
152
+ args[0].each do |b|
153
+ yield [b, b + p0, b - p0]
154
+ end
155
+ ' language 'plruby';
156
+
157
+ select * from
158
+ circle_val('{"<(5,1),3>","<(1,2),100>","<(100,200),10>","<(100,1),115>","1,3,5"}'::circle[]);
159
+
160
+ drop table pl_box cascade;
161
+
162
+ create table pl_box (
163
+ p circle, p0 circle, p1 circle
164
+ );
165
+
166
+ create or replace function circle_val(circle[]) returns setof pl_box as '
167
+ p0 = Point.new(6,7)
168
+ args[0].each do |b|
169
+ yield [b, p0 * b, p0 / b ]
170
+ end
171
+ ' language 'plruby';
172
+
173
+ select * from
174
+ circle_val('{"<(5,1),3>","<(1,2),100>","<(100,200),10>","<(100,1),115>","1,3,5"}'::circle[]);
175
+
176
+ drop table pl_box cascade;
177
+
178
+ create table pl_box (
179
+ overlap bool, overleft bool, overright bool,
180
+ bleft bool, bright bool, below bool, above bool
181
+ );
182
+
183
+ create or replace function circle_val(circle, circle) returns setof pl_box as '
184
+ b0 = args[0]
185
+ b1 = args[1]
186
+ yield b0.overlap?(b1), b0.overleft?(b1), b0.overright?(b1),
187
+ b0.left?(b1), b0.right?(b1), b0.below?(b1), b0.above?(b1)
188
+ ' language 'plruby';
189
+
190
+
191
+ select * from
192
+ circle_val('<(5,1),3>'::circle, '<(1,2),100>'::circle);
193
+
194
+ select * from
195
+ circle_val('<(100,200),10>'::circle, '<(100,1),115>'::circle);
196
+
@@ -0,0 +1,2494 @@
1
+ #include "convcommon.h"
2
+
3
+ #include <math.h>
4
+ #include <limits.h>
5
+ #include <float.h>
6
+ #include <ctype.h>
7
+
8
+ #include "libpq/pqformat.h"
9
+ #include "utils/geo_decls.h"
10
+
11
+ static VALUE pl_cPoint;
12
+
13
+ static VALUE
14
+ pl_convert(VALUE obj, ID id, void (*func)())
15
+ {
16
+ if (TYPE(obj) == T_DATA &&
17
+ RDATA(obj)->dmark == (RUBY_DATA_FUNC)func) {
18
+ return obj;
19
+ }
20
+ obj = rb_funcall(obj, id, 0, 0);
21
+ if (TYPE(obj) != T_DATA ||
22
+ RDATA(obj)->dmark != (RUBY_DATA_FUNC)func) {
23
+ rb_raise(rb_eArgError, "invalid conversion");
24
+ }
25
+ return obj;
26
+ }
27
+
28
+ static void pl_point_mark(Point *p) {}
29
+ static void pl_circle_mark(CIRCLE *l) {}
30
+ static void pl_poly_mark(POLYGON *l) {}
31
+
32
+ #define INIT_COPY(init_copy, type_struct, mark_func) \
33
+ static VALUE \
34
+ init_copy(VALUE copy, VALUE orig) \
35
+ { \
36
+ type_struct *t0, *t1; \
37
+ \
38
+ if (copy == orig) return copy; \
39
+ if (TYPE(orig) != T_DATA || \
40
+ RDATA(orig)->dmark != (RUBY_DATA_FUNC)mark_func) { \
41
+ rb_raise(rb_eTypeError, "wrong argument type to clone"); \
42
+ } \
43
+ Data_Get_Struct(orig, type_struct, t0); \
44
+ Data_Get_Struct(copy, type_struct, t1); \
45
+ MEMCPY(t1, t0, type_struct, 1); \
46
+ return copy; \
47
+ }
48
+
49
+ static VALUE
50
+ pl_point_s_alloc(VALUE obj)
51
+ {
52
+ Point *p;
53
+ return Data_Make_Struct(obj, Point, pl_point_mark, free, p);
54
+ }
55
+
56
+ INIT_COPY(pl_point_init_copy, Point, pl_point_mark);
57
+
58
+ static VALUE
59
+ pl_point_s_datum(VALUE obj, VALUE a)
60
+ {
61
+ Point *p0, *p1;
62
+ Oid typoid;
63
+ VALUE res;
64
+
65
+ p0 = (Point *)plruby_datum_get(a, &typoid);
66
+ if (typoid != POINTOID) {
67
+ rb_raise(rb_eArgError, "unknown OID type %d", typoid);
68
+ }
69
+ p1 = ALLOC_N(Point, 1);
70
+ memcpy(p1, p0, sizeof(Point));
71
+ res = Data_Wrap_Struct(obj, pl_point_mark, free, p1);
72
+ OBJ_TAINT(res);
73
+ return res;
74
+ }
75
+
76
+ static VALUE
77
+ pl_point_to_datum(VALUE obj, VALUE a)
78
+ {
79
+ Point *p0, *p1;
80
+ int typoid;
81
+
82
+ typoid = plruby_datum_oid(a, 0);
83
+ if (typoid != POINTOID) {
84
+ return Qnil;
85
+ }
86
+ Data_Get_Struct(obj, Point, p0);
87
+ p1 = (Point *)palloc(sizeof(Point));
88
+ memcpy(p1, p0, sizeof(Point));
89
+ return plruby_datum_set(a, (Datum)p1);
90
+ }
91
+
92
+ PL_MLOAD(pl_point_mload, point_recv, Point);
93
+ PL_MDUMP(pl_point_mdump, point_send);
94
+
95
+ static VALUE
96
+ pl_point_s_str(VALUE obj, VALUE a)
97
+ {
98
+ Point *p;
99
+ VALUE res;
100
+
101
+ a = plruby_to_s(a);
102
+ res = Data_Make_Struct(obj, Point, pl_point_mark, free, p);
103
+ CPY_FREE(p, PLRUBY_DFC1(point_in, RSTRING_PTR(a)), sizeof(Point));
104
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
105
+ return res;
106
+ }
107
+
108
+ static VALUE
109
+ pl_point_init(VALUE obj, VALUE a, VALUE b)
110
+ {
111
+ Point *point;
112
+
113
+ Data_Get_Struct(obj, Point, point);
114
+ a = rb_Float(a);
115
+ b = rb_Float(b);
116
+ point->x = RFLOAT_VALUE(a);
117
+ point->y = RFLOAT_VALUE(b);
118
+ return obj;
119
+ }
120
+
121
+ static VALUE
122
+ pl_point_x(VALUE obj)
123
+ {
124
+ Point *point;
125
+ VALUE res;
126
+
127
+ Data_Get_Struct(obj, Point, point);
128
+ res = rb_float_new(point->x);
129
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
130
+ return res;
131
+ }
132
+
133
+ static VALUE
134
+ pl_point_setx(VALUE obj, VALUE a)
135
+ {
136
+ Point *point;
137
+
138
+ Data_Get_Struct(obj, Point, point);
139
+ a = rb_Float(a);
140
+ point->x = RFLOAT_VALUE(a);
141
+ return a;
142
+ }
143
+
144
+ static VALUE
145
+ pl_point_y(VALUE obj)
146
+ {
147
+ Point *point;
148
+ VALUE res;
149
+
150
+ Data_Get_Struct(obj, Point, point);
151
+ res = rb_float_new(point->y);
152
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
153
+ return res;
154
+ }
155
+
156
+ static VALUE
157
+ pl_point_sety(VALUE obj, VALUE a)
158
+ {
159
+ Point *point;
160
+
161
+ Data_Get_Struct(obj, Point, point);
162
+ a = rb_Float(a);
163
+ point->y = RFLOAT_VALUE(a);
164
+ return a;
165
+ }
166
+
167
+ static VALUE
168
+ pl_point_aref(VALUE obj, VALUE a)
169
+ {
170
+ Point *point;
171
+ int i;
172
+ VALUE res;
173
+
174
+ Data_Get_Struct(obj, Point, point);
175
+ i = NUM2INT(rb_Integer(a));
176
+ if (i < 0) i = -i;
177
+ switch (i) {
178
+ case 0:
179
+ res = rb_float_new(point->x);
180
+ break;
181
+
182
+ case 1:
183
+ res = rb_float_new(point->y);
184
+ break;
185
+
186
+ default:
187
+ res = Qnil;
188
+ }
189
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
190
+ return res;
191
+ }
192
+
193
+ static VALUE
194
+ pl_point_aset(VALUE obj, VALUE a, VALUE b)
195
+ {
196
+ Point *point;
197
+ int i;
198
+
199
+ Data_Get_Struct(obj, Point, point);
200
+ i = NUM2INT(rb_Integer(a));
201
+ b = rb_Float(b);
202
+ if (i < 0) i = -i;
203
+ switch (i) {
204
+ case 0:
205
+ point->x = RFLOAT_VALUE(b);
206
+ break;
207
+ case 1:
208
+ point->y = RFLOAT_VALUE(b);
209
+ break;
210
+ default:
211
+ rb_raise(rb_eArgError, "[]= invalid indice");
212
+ }
213
+ return b;
214
+ }
215
+
216
+ #define TO_STRING(NAME_,FUNCTION_) \
217
+ static VALUE \
218
+ NAME_(VALUE obj) \
219
+ { \
220
+ Point *p; \
221
+ char *str; \
222
+ \
223
+ Data_Get_Struct(obj, Point, p); \
224
+ str = (char *)PLRUBY_DFC1(FUNCTION_, p); \
225
+ if (OBJ_TAINTED(obj)) { \
226
+ return rb_tainted_str_new2(str); \
227
+ } \
228
+ return rb_str_new2(str); \
229
+ }
230
+
231
+ TO_STRING(pl_point_to_s,point_out);
232
+
233
+ #define CHECK_CLASS(obj, a) \
234
+ if (!rb_obj_is_kind_of(a, rb_obj_class(obj))) { \
235
+ rb_raise(rb_eArgError, "invalid classes (%s, %s)", \
236
+ rb_class2name(rb_obj_class(obj)), \
237
+ rb_class2name(rb_obj_class(a))); \
238
+ }
239
+
240
+ #define POINT_CALL(NAME_,FUNCTION_) \
241
+ static VALUE \
242
+ NAME_(VALUE obj, VALUE a) \
243
+ { \
244
+ Point *p0, *p1, *pr; \
245
+ VALUE res; \
246
+ \
247
+ if (TYPE(a) == T_DATA && \
248
+ RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_point_mark) { \
249
+ Data_Get_Struct(obj, Point, p0); \
250
+ Data_Get_Struct(a, Point, p1); \
251
+ res = Data_Make_Struct(rb_obj_class(obj), Point, \
252
+ pl_point_mark, free, pr); \
253
+ CPY_FREE(pr, PLRUBY_DFC2(FUNCTION_, p0, p1), sizeof(Point)); \
254
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res); \
255
+ return res; \
256
+ } \
257
+ return rb_funcall(a, rb_frame_last_func(), 1, obj); \
258
+ }
259
+
260
+ POINT_CALL(pl_point_add,point_add);
261
+ POINT_CALL(pl_point_sub,point_sub);
262
+ POINT_CALL(pl_point_mul,point_mul);
263
+ POINT_CALL(pl_point_div,point_div);
264
+
265
+ #define POINT_CALL_BOOL(NAME_,FUNCTION_) \
266
+ static VALUE \
267
+ NAME_(VALUE obj, VALUE a) \
268
+ { \
269
+ Point *p0, *p1; \
270
+ \
271
+ CHECK_CLASS(obj, a); \
272
+ Data_Get_Struct(obj, Point, p0); \
273
+ Data_Get_Struct(a, Point, p1); \
274
+ if (PLRUBY_DFC2(FUNCTION_, p0, p1)) \
275
+ return Qtrue; \
276
+ return Qfalse; \
277
+ }
278
+
279
+ POINT_CALL_BOOL(pl_point_left,point_left);
280
+ POINT_CALL_BOOL(pl_point_right,point_right);
281
+ POINT_CALL_BOOL(pl_point_above,point_above);
282
+ POINT_CALL_BOOL(pl_point_below,point_below);
283
+ POINT_CALL_BOOL(pl_point_vert,point_vert);
284
+ POINT_CALL_BOOL(pl_point_horiz,point_horiz);
285
+ POINT_CALL_BOOL(pl_point_eq,point_eq);
286
+
287
+ #ifdef USE_FLOAT8_BYVAL
288
+ #define RETURN_FLOAT(obj_, function_) do { \
289
+ float8 f_; \
290
+ VALUE res_; \
291
+ f_ = DatumGetFloat8(function_); \
292
+ res_ = rb_float_new(f_); \
293
+ if (OBJ_TAINTED(obj_)) OBJ_TAINT(res_); \
294
+ return res_; \
295
+ } while (0)
296
+
297
+ #define RETURN_FLOAT2(obj_, a_, function_) do { \
298
+ float8 f_; \
299
+ VALUE res_; \
300
+ f_ = DatumGetFloat8(function_); \
301
+ res_ = rb_float_new(f_); \
302
+ if (OBJ_TAINTED(obj_) || \
303
+ OBJ_TAINTED(a_)) OBJ_TAINT(res_); \
304
+ return res_; \
305
+ } while (0)
306
+ #else
307
+ #define RETURN_FLOAT(obj_, function_) do { \
308
+ float8 *f_; \
309
+ VALUE res_; \
310
+ f_ = (float8 *)function_; \
311
+ if (!f_) res_ = rb_float_new(0.0); \
312
+ else { \
313
+ res_ = rb_float_new(*f_); \
314
+ pfree(f_); \
315
+ } \
316
+ if (OBJ_TAINTED(obj_)) OBJ_TAINT(res_); \
317
+ return res_; \
318
+ } while (0)
319
+
320
+ #define RETURN_FLOAT2(obj_, a_, function_) do { \
321
+ float8 *f_; \
322
+ VALUE res_; \
323
+ f_ = (float8 *)function_; \
324
+ if (!f_) res_ = rb_float_new(0.0); \
325
+ else { \
326
+ res_ = rb_float_new(*f_); \
327
+ pfree(f_); \
328
+ } \
329
+ if (OBJ_TAINTED(obj_) || \
330
+ OBJ_TAINTED(a_)) OBJ_TAINT(res_); \
331
+ return res_; \
332
+ } while (0)
333
+ #endif
334
+
335
+
336
+ static VALUE
337
+ pl_point_slope(VALUE obj, VALUE a)
338
+ {
339
+ Point *p0, *p1;
340
+
341
+ CHECK_CLASS(obj, a);
342
+ Data_Get_Struct(obj, Point, p0);
343
+ Data_Get_Struct(a, Point, p1);
344
+ RETURN_FLOAT2(obj, a, PLRUBY_DFC2(point_slope, p0, p1));
345
+ }
346
+
347
+ static void pl_lseg_mark(LSEG *l) {}
348
+
349
+ static VALUE
350
+ pl_lseg_s_alloc(VALUE obj)
351
+ {
352
+ LSEG *lseg;
353
+ return Data_Make_Struct(obj, LSEG, pl_lseg_mark, free, lseg);
354
+ }
355
+
356
+ INIT_COPY(pl_lseg_init_copy, LSEG, pl_lseg_mark);
357
+
358
+ static VALUE
359
+ pl_lseg_s_datum(VALUE obj, VALUE a)
360
+ {
361
+ LSEG *p0, *p1;
362
+ Oid typoid;
363
+ VALUE res;
364
+
365
+ p0 = (LSEG *)plruby_datum_get(a, &typoid);
366
+ if (typoid != LSEGOID) {
367
+ rb_raise(rb_eArgError, "unknown OID type %d", typoid);
368
+ }
369
+ p1 = ALLOC_N(LSEG, 1);
370
+ memcpy(p1, p0, sizeof(LSEG));
371
+ res = Data_Wrap_Struct(obj, pl_lseg_mark, free, p1);
372
+ OBJ_TAINT(res);
373
+ return res;
374
+ }
375
+
376
+ static VALUE
377
+ pl_lseg_to_datum(VALUE obj, VALUE a)
378
+ {
379
+ LSEG *p0, *p1;
380
+ int typoid;
381
+
382
+ typoid = plruby_datum_oid(a, 0);
383
+ if (typoid != LSEGOID) {
384
+ return Qnil;
385
+ }
386
+ Data_Get_Struct(obj, LSEG, p0);
387
+ p1 = (LSEG *)palloc(sizeof(LSEG));
388
+ memcpy(p1, p0, sizeof(LSEG));
389
+ return plruby_datum_set(a, (Datum)p1);
390
+ }
391
+
392
+ PL_MLOAD(pl_lseg_mload, lseg_recv, LSEG);
393
+ PL_MDUMP(pl_lseg_mdump, lseg_send);
394
+
395
+ static VALUE
396
+ pl_lseg_s_str(VALUE obj, VALUE a)
397
+ {
398
+ LSEG *l;
399
+ VALUE res;
400
+
401
+ a = plruby_to_s(a);
402
+ res = Data_Make_Struct(obj, LSEG, pl_lseg_mark, free, l);
403
+ CPY_FREE(l, PLRUBY_DFC1(lseg_in, RSTRING_PTR(a)), sizeof(LSEG));
404
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
405
+ return res;
406
+ }
407
+
408
+ static VALUE
409
+ pl_lseg_init(VALUE obj, VALUE a, VALUE b)
410
+ {
411
+ LSEG *l;
412
+ Point *p;
413
+
414
+ a = pl_convert(a, rb_intern("to_point"), pl_point_mark);
415
+ b = pl_convert(b, rb_intern("to_point"), pl_point_mark);
416
+ Data_Get_Struct(obj, LSEG, l);
417
+ Data_Get_Struct(a, Point, p);
418
+ l->p[0].x = p->x;
419
+ l->p[0].y = p->y;
420
+ Data_Get_Struct(b, Point, p);
421
+ l->p[1].x = p->x;
422
+ l->p[1].y = p->y;
423
+ return obj;
424
+ }
425
+
426
+ TO_STRING(pl_lseg_to_s,lseg_out);
427
+
428
+ static VALUE
429
+ pl_lseg_aref(VALUE obj, VALUE a)
430
+ {
431
+ LSEG *lseg;
432
+ Point *point;
433
+ int i;
434
+ VALUE res;
435
+
436
+ Data_Get_Struct(obj, LSEG, lseg);
437
+ i = NUM2INT(rb_Integer(a));
438
+ if (i < 0) i = -i;
439
+ switch (i) {
440
+ case 0:
441
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, point);
442
+ point->x = lseg->p[0].x;
443
+ point->y = lseg->p[0].y;
444
+ break;
445
+
446
+ case 1:
447
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, point);
448
+ point->x = lseg->p[1].x;
449
+ point->y = lseg->p[1].y;
450
+ break;
451
+
452
+ default:
453
+ res = Qnil;
454
+ }
455
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
456
+ return res;
457
+ }
458
+
459
+ static VALUE
460
+ pl_lseg_aset(VALUE obj, VALUE a, VALUE b)
461
+ {
462
+ LSEG *lseg;
463
+ Point *point;
464
+ int i;
465
+
466
+ Data_Get_Struct(obj, LSEG, lseg);
467
+ i = NUM2INT(rb_Integer(a));
468
+ b = pl_convert(b, rb_intern("to_point"), pl_point_mark);
469
+ Data_Get_Struct(b, Point, point);
470
+ if (i < 0) i = -i;
471
+ switch (i) {
472
+ case 0:
473
+ lseg->p[0].x = point->x;
474
+ lseg->p[0].y = point->y;
475
+ break;
476
+ case 1:
477
+ lseg->p[1].x = point->x;
478
+ lseg->p[1].y = point->y;
479
+ break;
480
+ default:
481
+ rb_raise(rb_eArgError, "[]= invalid indice");
482
+ }
483
+ return b;
484
+ }
485
+
486
+
487
+ static VALUE
488
+ pl_lseg_length(VALUE obj)
489
+ {
490
+ LSEG *l;
491
+
492
+ Data_Get_Struct(obj, LSEG, l);
493
+ RETURN_FLOAT(obj, PLRUBY_DFC1(lseg_length, l));
494
+ }
495
+
496
+ static VALUE
497
+ pl_lseg_parallel(VALUE obj, VALUE a)
498
+ {
499
+ LSEG *l0, *l1;
500
+
501
+ CHECK_CLASS(obj, a);
502
+ Data_Get_Struct(obj, LSEG, l0);
503
+ Data_Get_Struct(a, LSEG, l1);
504
+ if (PLRUBY_DFC2(lseg_parallel, l0, l1)) return Qtrue;
505
+ return Qfalse;
506
+ }
507
+
508
+ static VALUE
509
+ pl_lseg_perp(VALUE obj, VALUE a)
510
+ {
511
+ LSEG *l0, *l1;
512
+
513
+ CHECK_CLASS(obj, a);
514
+ Data_Get_Struct(obj, LSEG, l0);
515
+ Data_Get_Struct(a, LSEG, l1);
516
+ if (PLRUBY_DFC2(lseg_perp, l0, l1)) return Qtrue;
517
+ return Qfalse;
518
+ }
519
+
520
+ #define LSEG_BOOL(NAME_,FUNCTION_) \
521
+ static VALUE \
522
+ NAME_(VALUE obj) \
523
+ { \
524
+ LSEG *l; \
525
+ \
526
+ Data_Get_Struct(obj, LSEG, l); \
527
+ if (PLRUBY_DFC1(FUNCTION_, l)) return Qtrue;\
528
+ return Qfalse; \
529
+ }
530
+
531
+ LSEG_BOOL(pl_lseg_horizontal,lseg_horizontal);
532
+ LSEG_BOOL(pl_lseg_vertical,lseg_vertical);
533
+
534
+ static VALUE
535
+ pl_lseg_cmp(VALUE obj, VALUE a)
536
+ {
537
+ LSEG *l0, *l1;
538
+
539
+ if (!rb_obj_is_kind_of(a, rb_obj_class(obj))) {
540
+ return Qnil;
541
+ }
542
+ Data_Get_Struct(obj, LSEG, l0);
543
+ Data_Get_Struct(a, LSEG, l1);
544
+ if (PLRUBY_DFC2(lseg_eq, l0, l1)) return INT2NUM(0);
545
+ if (PLRUBY_DFC2(lseg_lt, l0, l1)) return INT2NUM(-1);
546
+ return INT2NUM(1);
547
+ }
548
+
549
+ static VALUE
550
+ pl_lseg_center(VALUE obj)
551
+ {
552
+ LSEG *l;
553
+ Point *p;
554
+ VALUE res;
555
+
556
+ Data_Get_Struct(obj, LSEG, l);
557
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, p);
558
+ CPY_FREE(p, PLRUBY_DFC1(lseg_center, l), sizeof(Point));
559
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
560
+ return res;
561
+ }
562
+
563
+ static VALUE
564
+ pl_lseg_closest(VALUE obj, VALUE a)
565
+ {
566
+ LSEG *l0, *l1;
567
+ Point *p0, *p1;
568
+ VALUE res;
569
+
570
+ Data_Get_Struct(obj, LSEG, l0);
571
+ if (TYPE(a) == T_DATA) {
572
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
573
+ Point *p;
574
+
575
+ Data_Get_Struct(a, Point, p);
576
+ p0 = (Point *)PLRUBY_DFC2(close_ps, p, l0);
577
+ if (!p0) return Qnil;
578
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, p1);
579
+ CPY_FREE(p1, p0, sizeof(Point));
580
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
581
+ return res;
582
+ }
583
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_lseg_mark) {
584
+ Data_Get_Struct(a, LSEG, l1);
585
+ p0 = (Point *)PLRUBY_DFC2(close_lseg, l0, l1);
586
+ if (!p0) return Qnil;
587
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, p1);
588
+ CPY_FREE(p1, p0, sizeof(Point));
589
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
590
+ return res;
591
+ }
592
+ }
593
+ return rb_funcall(a, rb_frame_last_func(), 1, obj);
594
+ }
595
+
596
+ static VALUE
597
+ pl_lseg_intersect(VALUE obj, VALUE a)
598
+ {
599
+ LSEG *l0, *l1;
600
+
601
+ Data_Get_Struct(obj, LSEG, l0);
602
+ if (TYPE(a) == T_DATA &&
603
+ RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_lseg_mark) {
604
+ Data_Get_Struct(a, LSEG, l1);
605
+ if (PLRUBY_DFC2(lseg_intersect, l0, l1)) return Qtrue;
606
+ return Qfalse;
607
+ }
608
+ return rb_funcall(a, rb_frame_last_func(), 1, obj);
609
+ }
610
+
611
+ static VALUE
612
+ pl_lseg_intersection(VALUE obj, VALUE a)
613
+ {
614
+ LSEG *l0, *l1;
615
+ Point *p0, *p1;
616
+ VALUE res;
617
+
618
+ Data_Get_Struct(obj, LSEG, l0);
619
+ if (!rb_obj_is_kind_of(a, rb_obj_class(obj))) {
620
+ rb_raise(rb_eArgError, "intersection : expected a Segment");
621
+ }
622
+ Data_Get_Struct(a, LSEG, l1);
623
+ p0 = (Point *)PLRUBY_DFC2(lseg_interpt, l0, l1);
624
+ if (!p0) return Qnil;
625
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, p1);
626
+ CPY_FREE(p1, p0, sizeof(Point));
627
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
628
+ return res;
629
+ }
630
+
631
+ static void pl_box_mark(BOX *l) {}
632
+
633
+ static VALUE
634
+ pl_box_s_alloc(VALUE obj)
635
+ {
636
+ BOX *box;
637
+ return Data_Make_Struct(obj, BOX, pl_box_mark, free, box);
638
+ }
639
+
640
+ INIT_COPY(pl_box_init_copy, BOX, pl_box_mark);
641
+
642
+ static VALUE
643
+ pl_box_s_datum(VALUE obj, VALUE a)
644
+ {
645
+ BOX *p0, *p1;
646
+ Oid typoid;
647
+ VALUE res;
648
+
649
+ p0 = (BOX *)plruby_datum_get(a, &typoid);
650
+ if (typoid != BOXOID) {
651
+ rb_raise(rb_eArgError, "unknown OID type %d", typoid);
652
+ }
653
+ p1 = ALLOC_N(BOX, 1);
654
+ memcpy(p1, p0, sizeof(BOX));
655
+ res = Data_Wrap_Struct(obj, pl_box_mark, free, p1);
656
+ OBJ_TAINT(res);
657
+ return res;
658
+ }
659
+
660
+ static VALUE
661
+ pl_box_to_datum(VALUE obj, VALUE a)
662
+ {
663
+ BOX *p0, *p1;
664
+ int typoid;
665
+
666
+ typoid = plruby_datum_oid(a, 0);
667
+ switch (typoid) {
668
+ case BOXOID:
669
+ break;
670
+
671
+ case CIRCLEOID:
672
+ obj = pl_convert(obj, rb_intern("to_circle"), pl_circle_mark);
673
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
674
+
675
+ case POLYGONOID:
676
+ obj = pl_convert(obj, rb_intern("to_poly"), pl_poly_mark);
677
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
678
+
679
+ case POINTOID:
680
+ obj = pl_convert(obj, rb_intern("to_point"), pl_point_mark);
681
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
682
+
683
+ default:
684
+ return Qnil;
685
+ }
686
+ Data_Get_Struct(obj, BOX, p0);
687
+ p1 = (BOX *)palloc(sizeof(BOX));
688
+ memcpy(p1, p0, sizeof(BOX));
689
+ return plruby_datum_set(a, (Datum)p1);
690
+ }
691
+
692
+ PL_MLOAD(pl_box_mload, box_recv, BOX);
693
+ PL_MDUMP(pl_box_mdump, box_send);
694
+
695
+ static VALUE
696
+ pl_box_s_str(VALUE obj, VALUE a)
697
+ {
698
+ BOX *l;
699
+ VALUE res;
700
+
701
+ a = plruby_to_s(a);
702
+ res = Data_Make_Struct(obj, BOX, pl_box_mark, free, l);
703
+ CPY_FREE(l, PLRUBY_DFC1(box_in, RSTRING_PTR(a)), sizeof(BOX));
704
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
705
+ return res;
706
+ }
707
+
708
+ static void
709
+ pl_box_adjust(BOX *bx)
710
+ {
711
+ if (bx->high.x < bx->low.x) {
712
+ double x = bx->high.x;
713
+ bx->high.x = bx->low.x;
714
+ bx->low.x = x;
715
+ }
716
+ if (bx->high.y < bx->low.y) {
717
+ double y = bx->high.y;
718
+ bx->high.y = bx->low.y;
719
+ bx->low.y = y;
720
+ }
721
+ }
722
+
723
+ static VALUE
724
+ pl_box_init(int argc, VALUE *argv, VALUE obj)
725
+ {
726
+ BOX *bx;
727
+
728
+ if (argc != 2 && argc != 4) {
729
+ rb_raise(rb_eArgError, "initialize : expected 2 Points");
730
+ }
731
+ Data_Get_Struct(obj, BOX, bx);
732
+ if (argc == 2) {
733
+ Point *p0, *p1;
734
+ VALUE a, b;
735
+
736
+ a = argv[0];
737
+ b = argv[1];
738
+ if (TYPE(a) != T_DATA ||
739
+ RDATA(a)->dmark != (RUBY_DATA_FUNC)pl_point_mark) {
740
+ a = pl_convert(a, rb_intern("to_point"), pl_point_mark);
741
+ }
742
+ if (TYPE(b) != T_DATA ||
743
+ RDATA(b)->dmark != (RUBY_DATA_FUNC)pl_point_mark) {
744
+ b = pl_convert(b, rb_intern("to_point"), pl_point_mark);
745
+ }
746
+ Data_Get_Struct(a, Point, p0);
747
+ Data_Get_Struct(b, Point, p1);
748
+ bx->low.x = p0->x;
749
+ bx->low.y = p0->y;
750
+ bx->high.x = p1->x;
751
+ bx->high.y = p1->y;
752
+ }
753
+ else {
754
+ bx->low.x = RFLOAT_VALUE(rb_Float(argv[0]));
755
+ bx->low.y = RFLOAT_VALUE(rb_Float(argv[1]));
756
+ bx->high.x = RFLOAT_VALUE(rb_Float(argv[2]));
757
+ bx->high.y = RFLOAT_VALUE(rb_Float(argv[3]));
758
+ }
759
+ pl_box_adjust(bx);
760
+ return obj;
761
+ }
762
+
763
+ TO_STRING(pl_box_to_s,box_out);
764
+
765
+ static VALUE
766
+ pl_box_aref(VALUE obj, VALUE a)
767
+ {
768
+ BOX *box;
769
+ Point *point;
770
+ int i;
771
+ VALUE res;
772
+
773
+ Data_Get_Struct(obj, BOX, box);
774
+ i = NUM2INT(rb_Integer(a));
775
+ if (i < 0) i = -i;
776
+ switch (i) {
777
+ case 0:
778
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, point);
779
+ point->x = box->low.x;
780
+ point->y = box->low.y;
781
+ break;
782
+
783
+ case 1:
784
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, point);
785
+ point->x = box->high.x;
786
+ point->y = box->high.y;
787
+ break;
788
+
789
+ default:
790
+ res = Qnil;
791
+ }
792
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
793
+ return res;
794
+ }
795
+
796
+ static VALUE
797
+ pl_box_low(VALUE obj)
798
+ {
799
+ BOX *box;
800
+ Point *point;
801
+ VALUE res;
802
+
803
+ Data_Get_Struct(obj, BOX, box);
804
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, point);
805
+ point->x = box->low.x;
806
+ point->y = box->low.y;
807
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
808
+ return res;
809
+ }
810
+
811
+ static VALUE
812
+ pl_box_high(VALUE obj)
813
+ {
814
+ BOX *box;
815
+ Point *point;
816
+ VALUE res;
817
+
818
+ Data_Get_Struct(obj, BOX, box);
819
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, point);
820
+ point->x = box->high.x;
821
+ point->y = box->high.y;
822
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
823
+ return res;
824
+ }
825
+
826
+ static VALUE
827
+ pl_box_aset(VALUE obj, VALUE a, VALUE b)
828
+ {
829
+ BOX *box;
830
+ Point *point;
831
+ int i;
832
+
833
+ Data_Get_Struct(obj, BOX, box);
834
+ i = NUM2INT(rb_Integer(a));
835
+ b = pl_convert(b, rb_intern("to_point"), pl_point_mark);
836
+ Data_Get_Struct(b, Point, point);
837
+ if (i < 0) i = -i;
838
+ switch (i) {
839
+ case 0:
840
+ box->low.x = point->x;
841
+ box->low.y = point->y;
842
+ break;
843
+ case 1:
844
+ box->high.x = point->x;
845
+ box->high.y = point->y;
846
+ break;
847
+ default:
848
+ rb_raise(rb_eArgError, "[]= invalid indice");
849
+ }
850
+ pl_box_adjust(box);
851
+ return b;
852
+ }
853
+
854
+ static VALUE
855
+ pl_box_lowset(VALUE obj, VALUE a)
856
+ {
857
+ BOX *box;
858
+ Point *point;
859
+
860
+ Data_Get_Struct(obj, BOX, box);
861
+ a = pl_convert(a, rb_intern("to_point"), pl_point_mark);
862
+ Data_Get_Struct(a, Point, point);
863
+ box->low.x = point->x;
864
+ box->low.y = point->y;
865
+ pl_box_adjust(box);
866
+ return a;
867
+ }
868
+
869
+ static VALUE
870
+ pl_box_highset(VALUE obj, VALUE a)
871
+ {
872
+ BOX *box;
873
+ Point *point;
874
+
875
+ Data_Get_Struct(obj, BOX, box);
876
+ a = pl_convert(a, rb_intern("to_point"), pl_point_mark);
877
+ Data_Get_Struct(a, Point, point);
878
+ box->high.x = point->x;
879
+ box->high.y = point->y;
880
+ pl_box_adjust(box);
881
+ return a;
882
+ }
883
+
884
+ static VALUE
885
+ pl_box_cmp(VALUE obj, VALUE a)
886
+ {
887
+ BOX *l0, *l1;
888
+
889
+ if (!rb_obj_is_kind_of(a, rb_obj_class(obj))) {
890
+ return Qnil;
891
+ }
892
+ Data_Get_Struct(obj, BOX, l0);
893
+ Data_Get_Struct(a, BOX, l1);
894
+ if (PLRUBY_DFC2(box_eq, l0, l1)) return INT2NUM(0);
895
+ if (PLRUBY_DFC2(box_lt, l0, l1)) return INT2NUM(-1);
896
+ return INT2NUM(1);
897
+ }
898
+
899
+ #define BOX_BOOL(NAME_,FUNCTION_) \
900
+ static VALUE \
901
+ NAME_(VALUE obj, VALUE a) \
902
+ { \
903
+ BOX *p0, *p1; \
904
+ \
905
+ CHECK_CLASS(obj, a); \
906
+ Data_Get_Struct(obj, BOX, p0); \
907
+ Data_Get_Struct(a, BOX, p1); \
908
+ if (PLRUBY_DFC2(FUNCTION_, p0, p1)) return Qtrue; \
909
+ return Qfalse; \
910
+ }
911
+
912
+ BOX_BOOL(pl_box_same,box_same);
913
+ BOX_BOOL(pl_box_overlap,box_overlap);
914
+ BOX_BOOL(pl_box_overleft,box_overleft);
915
+ BOX_BOOL(pl_box_left,box_left);
916
+ BOX_BOOL(pl_box_right,box_right);
917
+ BOX_BOOL(pl_box_overright,box_overright);
918
+ BOX_BOOL(pl_box_contained,box_contained);
919
+ BOX_BOOL(pl_box_contain,box_contain);
920
+ BOX_BOOL(pl_box_below,box_below);
921
+ BOX_BOOL(pl_box_above,box_above);
922
+
923
+ #define BOX_CALL(NAME_,FUNCTION_) \
924
+ static VALUE \
925
+ NAME_(VALUE obj, VALUE a) \
926
+ { \
927
+ BOX *p0, *pr; \
928
+ VALUE res; \
929
+ Point *pt; \
930
+ \
931
+ Data_Get_Struct(obj, BOX, p0); \
932
+ a = pl_convert(a, rb_intern("to_point"), pl_point_mark); \
933
+ Data_Get_Struct(a, Point, pt); \
934
+ res = Data_Make_Struct(rb_obj_class(obj), BOX, \
935
+ pl_box_mark, free, pr); \
936
+ CPY_FREE(pr, PLRUBY_DFC2(FUNCTION_, p0, pt), sizeof(BOX)); \
937
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res); \
938
+ return res; \
939
+ }
940
+
941
+ BOX_CALL(pl_box_add,box_add);
942
+ BOX_CALL(pl_box_sub,box_sub);
943
+ BOX_CALL(pl_box_mul,box_mul);
944
+ BOX_CALL(pl_box_div,box_div);
945
+
946
+ #define BOX_FLOAT(NAME_,FUNCTION_) \
947
+ static VALUE \
948
+ NAME_(VALUE obj) \
949
+ { \
950
+ BOX *l; \
951
+ \
952
+ Data_Get_Struct(obj, BOX, l); \
953
+ RETURN_FLOAT(obj, PLRUBY_DFC1(FUNCTION_, l));\
954
+ }
955
+
956
+ BOX_FLOAT(pl_box_area,box_area);
957
+ BOX_FLOAT(pl_box_height,box_height);
958
+ BOX_FLOAT(pl_box_width,box_width);
959
+
960
+ static VALUE
961
+ pl_box_center(VALUE obj)
962
+ {
963
+ BOX *b;
964
+ Point *p0, *p1;
965
+ VALUE res;
966
+
967
+ Data_Get_Struct(obj, BOX, b);
968
+ p0 = (Point *)PLRUBY_DFC1(box_center, b);
969
+ if (!p0) return Qnil;
970
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, p1);
971
+ CPY_FREE(p1, p0, sizeof(Point));
972
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
973
+ return res;
974
+ }
975
+
976
+ static VALUE
977
+ pl_box_closest(VALUE obj, VALUE a)
978
+ {
979
+ BOX *l0;
980
+ Point *p0, *p1;
981
+ VALUE res;
982
+
983
+ Data_Get_Struct(obj, BOX, l0);
984
+ if (TYPE(a) == T_DATA) {
985
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
986
+ Point *p;
987
+
988
+ Data_Get_Struct(a, Point, p);
989
+ p0 = (Point *)PLRUBY_DFC2(close_pb, p, l0);
990
+ if (!p0) return Qnil;
991
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, p1);
992
+ CPY_FREE(p1, p0, sizeof(Point));
993
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
994
+ return res;
995
+ }
996
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_lseg_mark) {
997
+ LSEG *p;
998
+
999
+ Data_Get_Struct(a, LSEG, p);
1000
+ p0 = (Point *)PLRUBY_DFC2(close_sb, p, l0);
1001
+ if (!p0) return Qnil;
1002
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, p1);
1003
+ CPY_FREE(p1, p0, sizeof(Point));
1004
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
1005
+ return res;
1006
+ }
1007
+ }
1008
+ rb_raise(rb_eArgError, "closest : invalid argument");
1009
+ return Qnil;
1010
+ }
1011
+
1012
+ static VALUE
1013
+ pl_box_intersect(VALUE obj, VALUE a)
1014
+ {
1015
+ BOX *l0;
1016
+
1017
+ Data_Get_Struct(obj, BOX, l0);
1018
+ if (TYPE(a) == T_DATA) {
1019
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_lseg_mark) {
1020
+ LSEG *p;
1021
+
1022
+ Data_Get_Struct(a, LSEG, p);
1023
+ if (PLRUBY_DFC2(inter_sb, p, l0)) return Qtrue;
1024
+ return Qfalse;
1025
+ }
1026
+ }
1027
+ rb_raise(rb_eArgError, "intersect : invalid argument");
1028
+ return Qnil;
1029
+ }
1030
+
1031
+ static VALUE
1032
+ pl_box_intersection(VALUE obj, VALUE a)
1033
+ {
1034
+ BOX *l0, *l1, *l2;
1035
+ VALUE res;
1036
+
1037
+ Data_Get_Struct(obj, BOX, l0);
1038
+ a = pl_convert(a, rb_intern("to_box"), pl_box_mark);
1039
+ Data_Get_Struct(a, BOX, l1);
1040
+ l1 = (BOX *)PLRUBY_DFC2(box_intersect, l0, l1);
1041
+ if (!l1) return Qnil;
1042
+ res = Data_Make_Struct(rb_obj_class(obj), BOX, pl_box_mark, free, l2);
1043
+ CPY_FREE(l2, l1, sizeof(BOX));
1044
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
1045
+ return res;
1046
+ }
1047
+
1048
+ static VALUE
1049
+ pl_box_diagonal(VALUE obj)
1050
+ {
1051
+ BOX *b;
1052
+ LSEG *l;
1053
+ VALUE res;
1054
+
1055
+ Data_Get_Struct(obj, BOX, b);
1056
+ res = Data_Make_Struct(obj, LSEG, pl_lseg_mark, free, l);
1057
+ CPY_FREE(l, PLRUBY_DFC1(box_diagonal, b), sizeof(LSEG));
1058
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1059
+ return res;
1060
+ }
1061
+
1062
+ static void pl_path_mark(PATH *l) {}
1063
+
1064
+ #ifndef SET_VARSIZE
1065
+ #define SET_VARSIZE(p__, s__) (p__)->size = s__
1066
+ #define GET_VARSIZE(t__, p__) (p__)->size
1067
+ #else
1068
+ #define GET_VARSIZE(t__, p__) (offsetof(t__, p[0]) + sizeof(p__->p[0]) * (p__)->npts)
1069
+ #endif
1070
+
1071
+ static VALUE
1072
+ pl_path_s_alloc(VALUE obj)
1073
+ {
1074
+ PATH *path;
1075
+ VALUE res;
1076
+ int sz;
1077
+
1078
+ res = Data_Make_Struct(obj, PATH, pl_path_mark, free, path);
1079
+ sz = GET_VARSIZE(PATH, path);
1080
+ SET_VARSIZE(path, sz);
1081
+ return res;
1082
+ }
1083
+
1084
+ static VALUE
1085
+ pl_path_init_copy(VALUE copy, VALUE orig)
1086
+ {
1087
+ PATH *p0, *p1;
1088
+ int sz0, sz1;
1089
+
1090
+ if (copy == orig) return copy;
1091
+ if (TYPE(orig) != T_DATA ||
1092
+ RDATA(orig)->dmark != (RUBY_DATA_FUNC)pl_path_mark) {
1093
+ rb_raise(rb_eTypeError, "wrong argument type to clone");
1094
+ }
1095
+ Data_Get_Struct(orig, PATH, p0);
1096
+ Data_Get_Struct(copy, PATH, p1);
1097
+ sz0 = GET_VARSIZE(PATH, p0);
1098
+ sz1 = GET_VARSIZE(PATH, p1);
1099
+ if (sz0 != sz1) {
1100
+ free(p1);
1101
+ RDATA(copy)->data = 0;
1102
+ p1 = (PATH *)ALLOC_N(char, sz0);
1103
+ SET_VARSIZE(p1, sz0);
1104
+ RDATA(copy)->data = p1;
1105
+ }
1106
+ memcpy(p1, p0, sz0);
1107
+ return copy;
1108
+ }
1109
+
1110
+ static VALUE
1111
+ pl_path_s_datum(VALUE obj, VALUE a)
1112
+ {
1113
+ PATH *p0, *p1;
1114
+ Oid typoid;
1115
+ VALUE res;
1116
+ int sz0;
1117
+
1118
+ p0 = (PATH *)plruby_datum_get(a, &typoid);
1119
+ if (typoid != PATHOID) {
1120
+ rb_raise(rb_eArgError, "unknown OID type %d", typoid);
1121
+ }
1122
+ sz0 = GET_VARSIZE(PATH, p0);
1123
+ p1 = (PATH *)ALLOC_N(char, sz0);
1124
+ memcpy(p1, p0, sz0);
1125
+ res = Data_Wrap_Struct(obj, pl_path_mark, free, p1);
1126
+ OBJ_TAINT(res);
1127
+ return res;
1128
+ }
1129
+
1130
+ static VALUE
1131
+ pl_path_to_datum(VALUE obj, VALUE a)
1132
+ {
1133
+ PATH *p0, *p1;
1134
+ int typoid;
1135
+ int sz0;
1136
+
1137
+ typoid = plruby_datum_oid(a, 0);
1138
+ switch (typoid) {
1139
+ case PATHOID:
1140
+ break;
1141
+
1142
+ case POLYGONOID:
1143
+ obj = pl_convert(obj, rb_intern("to_poly"), pl_poly_mark);
1144
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
1145
+
1146
+ case POINTOID:
1147
+ obj = pl_convert(obj, rb_intern("to_point"), pl_point_mark);
1148
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
1149
+
1150
+ default:
1151
+ return Qnil;
1152
+ }
1153
+ Data_Get_Struct(obj, PATH, p0);
1154
+ sz0 = GET_VARSIZE(PATH, p0);
1155
+ p1 = (PATH *)palloc(sz0);
1156
+ memcpy(p1, p0, sz0);
1157
+ return plruby_datum_set(a, (Datum)p1);
1158
+ }
1159
+
1160
+ #define PATHSIZE(p_) GET_VARSIZE(PATH, p_)
1161
+ PL_MLOADVAR(pl_path_mload, path_recv, PATH, PATHSIZE);
1162
+ PL_MDUMP(pl_path_mdump, path_send);
1163
+
1164
+ static VALUE
1165
+ pl_path_s_str(VALUE obj, VALUE a)
1166
+ {
1167
+ PATH *p, *m;
1168
+ VALUE res;
1169
+ int sz0;
1170
+
1171
+ a = plruby_to_s(a);
1172
+ m = (PATH *)PLRUBY_DFC1(path_in, RSTRING_PTR(a));
1173
+ sz0 = GET_VARSIZE(PATH, m);
1174
+ p = (PATH *)ALLOC_N(char, sz0);
1175
+ CPY_FREE(p, m, sz0);
1176
+ res = Data_Wrap_Struct(obj, pl_path_mark, free, p);
1177
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
1178
+ return res;
1179
+ }
1180
+
1181
+ static VALUE
1182
+ pl_path_init(int argc, VALUE *argv, VALUE obj)
1183
+ {
1184
+ PATH *p;
1185
+ VALUE a;
1186
+ int i, size, closed = Qfalse;
1187
+
1188
+ if (argc < 1 || argc > 2) {
1189
+ rb_raise(rb_eArgError, "expected Array of Points");
1190
+ }
1191
+ if (argc == 2) {
1192
+ closed = RTEST(argv[1]);
1193
+ }
1194
+ a = rb_Array(argv[0]);
1195
+ Data_Get_Struct(obj, PATH, p);
1196
+ free(p);
1197
+ size = offsetof(PATH, p[0]) + sizeof(p->p[0]) * RARRAY_LEN(a);
1198
+ p = (PATH *)ALLOC_N(char, size);
1199
+ MEMZERO(p, char, size);
1200
+ p->closed = closed;
1201
+ DATA_PTR(obj) = p;
1202
+ for (i = 0; i < RARRAY_LEN(a); ++i) {
1203
+ VALUE b = RARRAY_PTR(a)[i];
1204
+ if (TYPE(b) == T_DATA &&
1205
+ RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
1206
+ Point *po;
1207
+
1208
+ Data_Get_Struct(b, Point, po);
1209
+ p->p[i].x = po->x;
1210
+ p->p[i].y = po->y;
1211
+ }
1212
+ else {
1213
+ VALUE tmp;
1214
+
1215
+ b = rb_Array(b);
1216
+ if (RARRAY_LEN(b) != 2) {
1217
+ rb_raise(rb_eArgError, "initialize : expected Array [x, y]");
1218
+ }
1219
+ tmp = rb_Float(RARRAY_PTR(b)[0]);
1220
+ p->p[i].x = RFLOAT_VALUE(tmp);
1221
+ tmp = rb_Float(RARRAY_PTR(b)[1]);
1222
+ p->p[i].y = RFLOAT_VALUE(tmp);
1223
+ }
1224
+ }
1225
+ p->npts = RARRAY_LEN(a);
1226
+ return obj;
1227
+ }
1228
+
1229
+ TO_STRING(pl_path_to_s, path_out);
1230
+
1231
+ static VALUE
1232
+ pl_path_cmp(VALUE obj, VALUE a)
1233
+ {
1234
+ PATH *l0, *l1;
1235
+
1236
+ if (!rb_obj_is_kind_of(a, rb_obj_class(obj))) {
1237
+ return Qnil;
1238
+ }
1239
+ Data_Get_Struct(obj, PATH, l0);
1240
+ Data_Get_Struct(a, PATH, l1);
1241
+ if (PLRUBY_DFC2(path_n_eq, l0, l1)) return INT2NUM(0);
1242
+ if (PLRUBY_DFC2(path_n_lt, l0, l1)) return INT2NUM(-1);
1243
+ return INT2NUM(1);
1244
+ }
1245
+
1246
+ static VALUE
1247
+ pl_path_npoints(VALUE obj)
1248
+ {
1249
+ PATH *p;
1250
+ Data_Get_Struct(obj, PATH, p);
1251
+ return INT2NUM(p->npts);
1252
+ }
1253
+
1254
+ static VALUE
1255
+ pl_path_close(VALUE obj)
1256
+ {
1257
+ PATH *p;
1258
+ Data_Get_Struct(obj, PATH, p);
1259
+ p->closed = Qtrue;
1260
+ return obj;
1261
+ }
1262
+
1263
+ static VALUE
1264
+ pl_path_open(VALUE obj)
1265
+ {
1266
+ PATH *p;
1267
+ Data_Get_Struct(obj, PATH, p);
1268
+ p->closed = Qfalse;
1269
+ return obj;
1270
+ }
1271
+
1272
+ static VALUE
1273
+ pl_path_closed(VALUE obj)
1274
+ {
1275
+ PATH *p;
1276
+ Data_Get_Struct(obj, PATH, p);
1277
+ return (p->closed?Qtrue:Qfalse);
1278
+ }
1279
+
1280
+ static VALUE
1281
+ pl_path_length(VALUE obj)
1282
+ {
1283
+ PATH *p;
1284
+
1285
+ Data_Get_Struct(obj, PATH, p);
1286
+ RETURN_FLOAT(obj, PLRUBY_DFC1(path_length, p));
1287
+ }
1288
+
1289
+ #define PATH_CALL(NAME_, FUNCTION_) \
1290
+ static VALUE \
1291
+ NAME_(VALUE obj, VALUE a) \
1292
+ { \
1293
+ PATH *p0, *p1, *p2; \
1294
+ int size; \
1295
+ Point *p; \
1296
+ VALUE res; \
1297
+ \
1298
+ Data_Get_Struct(obj, PATH, p0); \
1299
+ if (TYPE(a) != T_DATA || \
1300
+ RDATA(a)->dmark != (RUBY_DATA_FUNC)pl_point_mark) { \
1301
+ a = pl_convert(a, rb_intern("to_point"), pl_point_mark); \
1302
+ } \
1303
+ Data_Get_Struct(a, Point, p); \
1304
+ p1 = (PATH *)PLRUBY_DFC2(FUNCTION_, p0, p); \
1305
+ size = GET_VARSIZE(PATH, p1); \
1306
+ p2 = (PATH *)ALLOC_N(char, size); \
1307
+ CPY_FREE(p2, p1, size); \
1308
+ res = Data_Wrap_Struct(rb_obj_class(obj), pl_path_mark, free, p2); \
1309
+ if (OBJ_TAINTED(obj)|| OBJ_TAINTED(a)) OBJ_TAINT(res); \
1310
+ return res; \
1311
+ }
1312
+
1313
+ PATH_CALL(pl_path_add, path_add_pt);
1314
+ PATH_CALL(pl_path_sub, path_sub_pt);
1315
+ PATH_CALL(pl_path_mul, path_mul_pt);
1316
+ PATH_CALL(pl_path_div, path_div_pt);
1317
+
1318
+ static VALUE
1319
+ pl_path_concat(VALUE obj, VALUE a)
1320
+ {
1321
+ PATH *p0, *p1;
1322
+ Point *p;
1323
+ int sz1;
1324
+
1325
+ Data_Get_Struct(obj, PATH, p0);
1326
+ a = pl_convert(a, rb_intern("to_path"), pl_path_mark);
1327
+ Data_Get_Struct(a, Point, p);
1328
+ p1 = (PATH *)PLRUBY_DFC2(path_add_pt, p0, p);
1329
+ free(p0);
1330
+ sz1 = GET_VARSIZE(PATH, p1);
1331
+ p0 = (PATH *)ALLOC_N(char, sz1);
1332
+ CPY_FREE(p0, p1, sz1);
1333
+ RDATA(obj)->data = p0;
1334
+ return obj;
1335
+ }
1336
+
1337
+ #if PG_PL_VERSION >= 75
1338
+
1339
+ static VALUE
1340
+ pl_path_area(VALUE obj)
1341
+ {
1342
+ PATH *p0;
1343
+
1344
+ Data_Get_Struct(obj, PATH, p0);
1345
+ RETURN_FLOAT(obj, PLRUBY_DFC1(path_area, p0));
1346
+ }
1347
+
1348
+ #endif
1349
+
1350
+
1351
+ /* Extracted from geo_utils.c */
1352
+
1353
+ /*------------------------------------------------------------------
1354
+ * The following routines define a data type and operator class for
1355
+ * POLYGONS .... Part of which (the polygon's bounding box) is built on
1356
+ * top of the BOX data type.
1357
+ *
1358
+ * make_bound_box - create the bounding box for the input polygon
1359
+ *------------------------------------------------------------------*/
1360
+
1361
+ /*---------------------------------------------------------------------
1362
+ * Make the smallest bounding box for the given polygon.
1363
+ *---------------------------------------------------------------------*/
1364
+ static void
1365
+ make_bound_box(POLYGON *poly)
1366
+ {
1367
+ int i;
1368
+ double x1, y1, x2, y2;
1369
+
1370
+ if (poly->npts > 0) {
1371
+ x2 = x1 = poly->p[0].x;
1372
+ y2 = y1 = poly->p[0].y;
1373
+ for (i = 1; i < poly->npts; i++) {
1374
+ if (poly->p[i].x < x1)
1375
+ x1 = poly->p[i].x;
1376
+ if (poly->p[i].x > x2)
1377
+ x2 = poly->p[i].x;
1378
+ if (poly->p[i].y < y1)
1379
+ y1 = poly->p[i].y;
1380
+ if (poly->p[i].y > y2)
1381
+ y2 = poly->p[i].y;
1382
+ }
1383
+ poly->boundbox.low.x = x1;
1384
+ poly->boundbox.low.y = y1;
1385
+ poly->boundbox.high.x = x2;
1386
+ poly->boundbox.high.y = y2;
1387
+ pl_box_adjust(&(poly->boundbox));
1388
+ }
1389
+ else {
1390
+ rb_raise(rb_eArgError, "can't create bounding box for empty polygon");
1391
+ }
1392
+ }
1393
+
1394
+ static VALUE
1395
+ pl_poly_s_alloc(VALUE obj)
1396
+ {
1397
+ POLYGON *poly;
1398
+ VALUE res;
1399
+ int sz;
1400
+
1401
+ res = Data_Make_Struct(obj, POLYGON, pl_poly_mark, free, poly);
1402
+ sz = GET_VARSIZE(POLYGON, poly);
1403
+ SET_VARSIZE(poly, sz);
1404
+ return res;
1405
+ }
1406
+
1407
+ static VALUE
1408
+ pl_poly_init_copy(VALUE copy, VALUE orig)
1409
+ {
1410
+ POLYGON *p0, *p1;
1411
+ int sz0, sz1;
1412
+
1413
+ if (copy == orig) return copy;
1414
+ if (TYPE(orig) != T_DATA ||
1415
+ RDATA(orig)->dmark != (RUBY_DATA_FUNC)pl_poly_mark) {
1416
+ rb_raise(rb_eTypeError, "wrong argument type to clone");
1417
+ }
1418
+ Data_Get_Struct(orig, POLYGON, p0);
1419
+ Data_Get_Struct(copy, POLYGON, p1);
1420
+ sz0 = GET_VARSIZE(POLYGON, p0);
1421
+ sz1 = GET_VARSIZE(POLYGON, p1);
1422
+ if (sz0 != sz1) {
1423
+ free(p1);
1424
+ RDATA(copy)->data = 0;
1425
+ p1 = (POLYGON *)ALLOC_N(char, sz0);
1426
+ SET_VARSIZE(p1, sz0);
1427
+ RDATA(copy)->data = p1;
1428
+ }
1429
+ memcpy(p1, p0, sz0);
1430
+ return copy;
1431
+ }
1432
+
1433
+ static VALUE
1434
+ pl_poly_s_datum(VALUE obj, VALUE a)
1435
+ {
1436
+ POLYGON *p0, *p1;
1437
+ Oid typoid;
1438
+ VALUE res;
1439
+ int sz0;
1440
+
1441
+ p0 = (POLYGON *)plruby_datum_get(a, &typoid);
1442
+ if (typoid != POLYGONOID) {
1443
+ rb_raise(rb_eArgError, "unknown OID type %d", typoid);
1444
+ }
1445
+ sz0 = GET_VARSIZE(POLYGON, p0);
1446
+ p1 = (POLYGON *)ALLOC_N(char, sz0);
1447
+ memcpy(p1, p0, sz0);
1448
+ res = Data_Wrap_Struct(obj, pl_poly_mark, free, p1);
1449
+ OBJ_TAINT(res);
1450
+ return res;
1451
+ }
1452
+
1453
+ static VALUE
1454
+ pl_poly_to_datum(VALUE obj, VALUE a)
1455
+ {
1456
+ POLYGON *p0, *p1;
1457
+ int typoid;
1458
+ int sz0;
1459
+
1460
+ typoid = plruby_datum_oid(a, 0);
1461
+ switch (typoid) {
1462
+ case POLYGONOID:
1463
+ break;
1464
+
1465
+ case CIRCLEOID:
1466
+ obj = pl_convert(obj, rb_intern("to_circle"), pl_circle_mark);
1467
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
1468
+
1469
+ case PATHOID:
1470
+ obj = pl_convert(obj, rb_intern("to_path"), pl_path_mark);
1471
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
1472
+
1473
+ case BOXOID:
1474
+ obj = pl_convert(obj, rb_intern("to_box"), pl_box_mark);
1475
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
1476
+
1477
+ case POINTOID:
1478
+ obj = pl_convert(obj, rb_intern("to_point"), pl_point_mark);
1479
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
1480
+
1481
+ default:
1482
+ return Qnil;
1483
+ }
1484
+ Data_Get_Struct(obj, POLYGON, p0);
1485
+ sz0 = GET_VARSIZE(POLYGON, p0);
1486
+ p1 = (POLYGON *)palloc(sz0);
1487
+ memcpy(p1, p0, sz0);
1488
+ return plruby_datum_set(a, (Datum)p1);
1489
+ }
1490
+
1491
+ #define POLYSIZE(p_) GET_VARSIZE(POLYGON, p_)
1492
+ PL_MLOADVAR(pl_poly_mload, poly_recv, POLYGON, POLYSIZE);
1493
+ PL_MDUMP(pl_poly_mdump, poly_send);
1494
+
1495
+ static VALUE
1496
+ pl_poly_s_str(VALUE obj, VALUE a)
1497
+ {
1498
+ POLYGON *p, *m;
1499
+ VALUE res;
1500
+ int sz0;
1501
+
1502
+ a = plruby_to_s(a);
1503
+ m = (POLYGON *)PLRUBY_DFC1(poly_in, RSTRING_PTR(a));
1504
+ sz0 = GET_VARSIZE(POLYGON, m);
1505
+ p = (POLYGON *)ALLOC_N(char, sz0);
1506
+ CPY_FREE(p, m, sz0);
1507
+ res = Data_Wrap_Struct(obj, pl_poly_mark, free, p);
1508
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
1509
+ return res;
1510
+ }
1511
+
1512
+ static VALUE
1513
+ pl_poly_init(int argc, VALUE *argv, VALUE obj)
1514
+ {
1515
+ POLYGON *p;
1516
+ VALUE a;
1517
+ int i, size, closed = Qfalse;
1518
+
1519
+ if (argc < 1 || argc > 2) {
1520
+ rb_raise(rb_eArgError, "initialize : expected Array of Points");
1521
+ }
1522
+ if (argc == 2) {
1523
+ closed = RTEST(argv[1]);
1524
+ }
1525
+ a = rb_Array(argv[0]);
1526
+ Data_Get_Struct(obj, POLYGON, p);
1527
+ free(p);
1528
+ size = offsetof(POLYGON, p[0]) + sizeof(p->p[0]) * RARRAY_LEN(a);
1529
+ p = (POLYGON *)ALLOC_N(char, size);
1530
+ MEMZERO(p, char, size);
1531
+ DATA_PTR(obj) = p;
1532
+ p->npts = RARRAY_LEN(a);
1533
+ for (i = 0; i < p->npts; ++i) {
1534
+ VALUE b = RARRAY_PTR(a)[i];
1535
+ if (TYPE(b) == T_DATA &&
1536
+ RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
1537
+ Point *po;
1538
+
1539
+ Data_Get_Struct(b, Point, po);
1540
+ p->p[i].x = po->x;
1541
+ p->p[i].y = po->y;
1542
+ }
1543
+ else {
1544
+ VALUE tmp;
1545
+
1546
+ b = rb_Array(b);
1547
+ if (RARRAY_LEN(b) != 2) {
1548
+ rb_raise(rb_eArgError, "initialize : expected Array [x, y]");
1549
+ }
1550
+ tmp = rb_Float(RARRAY_PTR(b)[0]);
1551
+ p->p[i].x = RFLOAT_VALUE(tmp);
1552
+ tmp = rb_Float(RARRAY_PTR(b)[1]);
1553
+ p->p[i].y = RFLOAT_VALUE(tmp);
1554
+ }
1555
+ }
1556
+ make_bound_box(p);
1557
+ return obj;
1558
+ }
1559
+
1560
+ TO_STRING(pl_poly_to_s, poly_out);
1561
+
1562
+ #define POLY_BOOL(NAME_,FUNCTION_) \
1563
+ static VALUE \
1564
+ NAME_(VALUE obj, VALUE a) \
1565
+ { \
1566
+ POLYGON *p0, *p1; \
1567
+ \
1568
+ CHECK_CLASS(obj, a); \
1569
+ Data_Get_Struct(obj, POLYGON, p0); \
1570
+ Data_Get_Struct(a, POLYGON, p1); \
1571
+ if (PLRUBY_DFC2(FUNCTION_, p0, p1)) return Qtrue;\
1572
+ return Qfalse; \
1573
+ }
1574
+
1575
+ POLY_BOOL(pl_poly_same,poly_same);
1576
+ POLY_BOOL(pl_poly_overlap,poly_overlap);
1577
+ POLY_BOOL(pl_poly_overleft,poly_overleft);
1578
+ POLY_BOOL(pl_poly_left,poly_left);
1579
+ POLY_BOOL(pl_poly_right,poly_right);
1580
+ POLY_BOOL(pl_poly_overright,poly_overright);
1581
+ POLY_BOOL(pl_poly_contained,poly_contained);
1582
+
1583
+ static VALUE
1584
+ pl_poly_contain(VALUE obj, VALUE a)
1585
+ {
1586
+ POLYGON *p0;
1587
+
1588
+ Data_Get_Struct(obj, POLYGON, p0);
1589
+ if (TYPE(a) != T_DATA) {
1590
+ rb_raise(rb_eArgError, "contain : expected a geometry object");
1591
+ }
1592
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
1593
+ Point *p1;
1594
+
1595
+ Data_Get_Struct(a, Point, p1);
1596
+ if (PLRUBY_DFC2(poly_contain_pt, p0, p1)) return Qtrue;
1597
+ return Qfalse;
1598
+ }
1599
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_poly_mark) {
1600
+ POLYGON *p1;
1601
+
1602
+ Data_Get_Struct(a, POLYGON, p1);
1603
+ if (PLRUBY_DFC2(poly_contain, p0, p1)) return Qtrue;
1604
+ return Qfalse;
1605
+ }
1606
+ rb_raise(rb_eArgError, "invalid geometry object");
1607
+ return Qnil;
1608
+ }
1609
+
1610
+ static VALUE
1611
+ pl_poly_npoints(VALUE obj)
1612
+ {
1613
+ POLYGON *p;
1614
+ Data_Get_Struct(obj, POLYGON, p);
1615
+ return INT2NUM(p->npts);
1616
+ }
1617
+
1618
+ static VALUE
1619
+ pl_poly_center(VALUE obj)
1620
+ {
1621
+ POLYGON *p;
1622
+ Point *p0, *p1;
1623
+ VALUE res;
1624
+
1625
+ Data_Get_Struct(obj, POLYGON, p);
1626
+ p0 = (Point *)PLRUBY_DFC1(poly_center, p);
1627
+ if (!p0) return Qnil;
1628
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, p1);
1629
+ CPY_FREE(p1, p0, sizeof(Point));
1630
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1631
+ return res;
1632
+ }
1633
+
1634
+ static VALUE pl_cPoly, pl_cBox, pl_cPath;
1635
+
1636
+ static VALUE
1637
+ pl_box_to_poly(VALUE obj)
1638
+ {
1639
+ BOX *b;
1640
+ POLYGON *p0, *p1;
1641
+ VALUE res;
1642
+ int sz0;
1643
+
1644
+ Data_Get_Struct(obj, BOX, b);
1645
+ p0 = (POLYGON *)PLRUBY_DFC1(box_poly, b);
1646
+ if (!p0) return Qnil;
1647
+ sz0 = GET_VARSIZE(POLYGON, p0);
1648
+ p1 = (POLYGON *)ALLOC_N(char, sz0);
1649
+ CPY_FREE(p1, p0, sz0);
1650
+ res = Data_Wrap_Struct(pl_cPoly, pl_poly_mark, free, p1);
1651
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1652
+ return res;
1653
+ }
1654
+
1655
+ static VALUE
1656
+ pl_path_to_poly(VALUE obj)
1657
+ {
1658
+ PATH *b;
1659
+ POLYGON *p0, *p1;
1660
+ VALUE res;
1661
+ int sz0;
1662
+
1663
+ Data_Get_Struct(obj, PATH, b);
1664
+ p0 = (POLYGON *)PLRUBY_DFC1(path_poly, b);
1665
+ if (!p0) return Qnil;
1666
+ sz0 = GET_VARSIZE(POLYGON, p0);
1667
+ p1 = (POLYGON *)ALLOC_N(char, sz0);
1668
+ CPY_FREE(p1, p0, sz0);
1669
+ res = Data_Wrap_Struct(pl_cPoly, pl_poly_mark, free, p1);
1670
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1671
+ return res;
1672
+ }
1673
+
1674
+ static VALUE
1675
+ pl_poly_to_path(VALUE obj)
1676
+ {
1677
+ POLYGON *b;
1678
+ PATH *p0, *p1;
1679
+ VALUE res;
1680
+ int sz0;
1681
+
1682
+ Data_Get_Struct(obj, POLYGON, b);
1683
+ p0 = (PATH *)PLRUBY_DFC1(poly_path, b);
1684
+ if (!p0) return Qnil;
1685
+ sz0 = GET_VARSIZE(PATH, p0);
1686
+ p1 = (PATH *)ALLOC_N(char, sz0);
1687
+ CPY_FREE(p1, p0, sz0);
1688
+ res = Data_Wrap_Struct(pl_cPath, pl_path_mark, free, p1);
1689
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1690
+ return res;
1691
+ }
1692
+
1693
+ static VALUE
1694
+ pl_poly_to_box(VALUE obj)
1695
+ {
1696
+ POLYGON *b;
1697
+ BOX *p0, *p1;
1698
+ VALUE res;
1699
+
1700
+ Data_Get_Struct(obj, POLYGON, b);
1701
+ p0 = (BOX *)PLRUBY_DFC1(poly_box, b);
1702
+ if (!p0) return Qnil;
1703
+ res = Data_Make_Struct(pl_cBox, BOX, pl_box_mark, free, p1);
1704
+ CPY_FREE(p1, p0, sizeof(BOX));
1705
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1706
+ return res;
1707
+ }
1708
+
1709
+ static VALUE
1710
+ pl_circle_s_alloc(VALUE obj)
1711
+ {
1712
+ CIRCLE *circle;
1713
+ return Data_Make_Struct(obj, CIRCLE, pl_circle_mark, free, circle);
1714
+ }
1715
+
1716
+ INIT_COPY(pl_circle_init_copy, CIRCLE, pl_circle_mark);
1717
+
1718
+ static VALUE
1719
+ pl_circle_s_datum(VALUE obj, VALUE a)
1720
+ {
1721
+ CIRCLE *p0, *p1;
1722
+ Oid typoid;
1723
+ VALUE res;
1724
+
1725
+ p0 = (CIRCLE *)plruby_datum_get(a, &typoid);
1726
+ if (typoid != CIRCLEOID) {
1727
+ rb_raise(rb_eArgError, "unknown OID type %d", typoid);
1728
+ }
1729
+ p1 = ALLOC_N(CIRCLE, 1);
1730
+ memcpy(p1, p0, sizeof(CIRCLE));
1731
+ res = Data_Wrap_Struct(obj, pl_circle_mark, free, p1);
1732
+ OBJ_TAINT(res);
1733
+ return res;
1734
+ }
1735
+
1736
+ static VALUE
1737
+ pl_circle_to_datum(VALUE obj, VALUE a)
1738
+ {
1739
+ CIRCLE *p0, *p1;
1740
+ int typoid;
1741
+
1742
+ typoid = plruby_datum_oid(a, 0);
1743
+ switch (typoid) {
1744
+ case CIRCLEOID:
1745
+ break;
1746
+
1747
+ case BOXOID:
1748
+ obj = pl_convert(obj, rb_intern("to_box"), pl_box_mark);
1749
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
1750
+
1751
+ case POLYGONOID:
1752
+ obj = pl_convert(obj, rb_intern("to_poly"), pl_poly_mark);
1753
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
1754
+
1755
+ case POINTOID:
1756
+ obj = pl_convert(obj, rb_intern("to_point"), pl_point_mark);
1757
+ return rb_funcall(obj, rb_frame_last_func(), 1, a);
1758
+
1759
+ default:
1760
+ return Qnil;
1761
+ }
1762
+ Data_Get_Struct(obj, CIRCLE, p0);
1763
+ p1 = (CIRCLE *)palloc(sizeof(CIRCLE));
1764
+ memcpy(p1, p0, sizeof(CIRCLE));
1765
+ return plruby_datum_set(a, (Datum)p1);
1766
+ }
1767
+
1768
+ PL_MLOAD(pl_circle_mload, circle_recv, CIRCLE);
1769
+ PL_MDUMP(pl_circle_mdump, circle_send);
1770
+
1771
+ static VALUE
1772
+ pl_circle_s_str(VALUE obj, VALUE a)
1773
+ {
1774
+ CIRCLE *p, *m;
1775
+ VALUE res;
1776
+
1777
+ a = plruby_to_s(a);
1778
+ m = (CIRCLE *)PLRUBY_DFC1(circle_in, RSTRING_PTR(a));
1779
+ res = Data_Make_Struct(obj, CIRCLE, pl_circle_mark, free, p);
1780
+ CPY_FREE(p, m, sizeof(CIRCLE));
1781
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
1782
+ return res;
1783
+ }
1784
+
1785
+ static VALUE
1786
+ pl_circle_init(VALUE obj, VALUE a, VALUE b)
1787
+ {
1788
+ CIRCLE *p;
1789
+
1790
+ Data_Get_Struct(obj, CIRCLE, p);
1791
+ if (TYPE(a) == T_DATA &&
1792
+ RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
1793
+ Point *po;
1794
+
1795
+ Data_Get_Struct(a, Point, po);
1796
+ p->center.x = po->x;
1797
+ p->center.y = po->y;
1798
+ }
1799
+ else {
1800
+ VALUE tmp;
1801
+
1802
+ a = rb_Array(a);
1803
+ if (RARRAY_LEN(a) != 2) {
1804
+ rb_raise(rb_eArgError, "initialize : expected Array [x, y]");
1805
+ }
1806
+ tmp = rb_Float(RARRAY_PTR(a)[0]);
1807
+ p->center.x = RFLOAT_VALUE(tmp);
1808
+ tmp = rb_Float(RARRAY_PTR(a)[1]);
1809
+ p->center.y = RFLOAT_VALUE(tmp);
1810
+ }
1811
+ p->radius = RFLOAT_VALUE(rb_Float(b));
1812
+ return obj;
1813
+ }
1814
+
1815
+ TO_STRING(pl_circle_to_s, circle_out);
1816
+
1817
+ #define CIRCLE_BOOL(NAME_,FUNCTION_) \
1818
+ static VALUE \
1819
+ NAME_(VALUE obj, VALUE a) \
1820
+ { \
1821
+ CIRCLE *p0, *p1; \
1822
+ \
1823
+ CHECK_CLASS(obj, a); \
1824
+ Data_Get_Struct(obj, CIRCLE, p0); \
1825
+ Data_Get_Struct(a, CIRCLE, p1); \
1826
+ if (PLRUBY_DFC2(FUNCTION_, p0, p1)) return Qtrue;\
1827
+ return Qfalse; \
1828
+ }
1829
+
1830
+ CIRCLE_BOOL(pl_circle_same,circle_same);
1831
+ CIRCLE_BOOL(pl_circle_overlap,circle_overlap);
1832
+ CIRCLE_BOOL(pl_circle_overleft,circle_overleft);
1833
+ CIRCLE_BOOL(pl_circle_left,circle_left);
1834
+ CIRCLE_BOOL(pl_circle_right,circle_right);
1835
+ CIRCLE_BOOL(pl_circle_overright,circle_overright);
1836
+ CIRCLE_BOOL(pl_circle_contained,circle_contained);
1837
+ CIRCLE_BOOL(pl_circle_below,circle_below);
1838
+ CIRCLE_BOOL(pl_circle_above,circle_above);
1839
+
1840
+ static VALUE
1841
+ pl_circle_contain(VALUE obj, VALUE a)
1842
+ {
1843
+ CIRCLE *p0;
1844
+
1845
+ Data_Get_Struct(obj, CIRCLE, p0);
1846
+ if (TYPE(a) != T_DATA) {
1847
+ rb_raise(rb_eArgError, "contain : expected a geometry object");
1848
+ }
1849
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
1850
+ Point *p1;
1851
+
1852
+ Data_Get_Struct(a, Point, p1);
1853
+ if (PLRUBY_DFC2(circle_contain_pt, p0, p1)) return Qtrue;
1854
+ return Qfalse;
1855
+ }
1856
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_circle_mark) {
1857
+ CIRCLE *p1;
1858
+
1859
+ Data_Get_Struct(a, CIRCLE, p1);
1860
+ if (PLRUBY_DFC2(circle_contain, p0, p1)) return Qtrue;
1861
+ return Qfalse;
1862
+ }
1863
+ rb_raise(rb_eArgError, "contain : invalid geometry object");
1864
+ return Qnil;
1865
+ }
1866
+
1867
+ #define CIRCLE_CALL(NAME_,FUNCTION_) \
1868
+ static VALUE \
1869
+ NAME_(VALUE obj, VALUE a) \
1870
+ { \
1871
+ CIRCLE *p0, *pr; \
1872
+ Point *pt; \
1873
+ VALUE res; \
1874
+ \
1875
+ Data_Get_Struct(obj, CIRCLE, p0); \
1876
+ if (TYPE(a) != T_DATA || \
1877
+ RDATA(a)->dmark != (RUBY_DATA_FUNC)pl_point_mark) { \
1878
+ a = pl_convert(a, rb_intern("to_point"), pl_point_mark); \
1879
+ } \
1880
+ Data_Get_Struct(a, Point, pt); \
1881
+ res = Data_Make_Struct(rb_obj_class(obj), CIRCLE, \
1882
+ pl_circle_mark, free, pr); \
1883
+ CPY_FREE(pr, PLRUBY_DFC2(FUNCTION_, p0, pt), sizeof(CIRCLE)); \
1884
+ if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res); \
1885
+ return res; \
1886
+ }
1887
+
1888
+ CIRCLE_CALL(pl_circle_add,circle_add_pt);
1889
+ CIRCLE_CALL(pl_circle_sub,circle_sub_pt);
1890
+ CIRCLE_CALL(pl_circle_mul,circle_mul_pt);
1891
+ CIRCLE_CALL(pl_circle_div,circle_div_pt);
1892
+
1893
+ #define CIRCLE_FLOAT(NAME_,FUNCTION_) \
1894
+ static VALUE \
1895
+ NAME_(VALUE obj) \
1896
+ { \
1897
+ CIRCLE *l; \
1898
+ \
1899
+ Data_Get_Struct(obj, CIRCLE, l); \
1900
+ RETURN_FLOAT(obj, PLRUBY_DFC1(FUNCTION_, l));\
1901
+ }
1902
+
1903
+ CIRCLE_FLOAT(pl_circle_area,circle_area);
1904
+ CIRCLE_FLOAT(pl_circle_radius,circle_radius);
1905
+ CIRCLE_FLOAT(pl_circle_diameter,circle_diameter);
1906
+
1907
+ static VALUE
1908
+ pl_circle_cmp(VALUE obj, VALUE a)
1909
+ {
1910
+ CIRCLE *l0, *l1;
1911
+
1912
+ if (!rb_obj_is_kind_of(a, rb_obj_class(obj))) {
1913
+ return Qnil;
1914
+ }
1915
+ Data_Get_Struct(obj, CIRCLE, l0);
1916
+ Data_Get_Struct(a, CIRCLE, l1);
1917
+ if (PLRUBY_DFC2(circle_eq, l0, l1)) return INT2NUM(0);
1918
+ if (PLRUBY_DFC2(circle_lt, l0, l1)) return INT2NUM(-1);
1919
+ return INT2NUM(1);
1920
+ }
1921
+
1922
+ static VALUE
1923
+ pl_circle_center(VALUE obj)
1924
+ {
1925
+ CIRCLE *l0;
1926
+ Point *p0, *p1;
1927
+ VALUE res;
1928
+
1929
+ Data_Get_Struct(obj, CIRCLE, l0);
1930
+ p0 = (Point *)PLRUBY_DFC1(circle_center, l0);
1931
+ if (!p0) return Qnil;
1932
+ res = Data_Make_Struct(pl_cPoint, Point, pl_point_mark, free, p1);
1933
+ CPY_FREE(p1, p0, sizeof(Point));
1934
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1935
+ return res;
1936
+ }
1937
+
1938
+ static VALUE pl_cCircle;
1939
+
1940
+ static VALUE
1941
+ pl_box_to_circle(VALUE obj)
1942
+ {
1943
+ BOX *b;
1944
+ CIRCLE *p0, *p1;
1945
+ VALUE res;
1946
+
1947
+ Data_Get_Struct(obj, BOX, b);
1948
+ p0 = (CIRCLE *)PLRUBY_DFC1(box_circle, b);
1949
+ if (!p0) return Qnil;
1950
+ res = Data_Make_Struct(pl_cCircle, CIRCLE, pl_circle_mark, free, p1);
1951
+ CPY_FREE(p1, p0, sizeof(CIRCLE));
1952
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1953
+ return res;
1954
+ }
1955
+
1956
+ static VALUE
1957
+ pl_poly_to_circle(VALUE obj)
1958
+ {
1959
+ POLYGON *b;
1960
+ CIRCLE *p0, *p1;
1961
+ VALUE res;
1962
+
1963
+ Data_Get_Struct(obj, POLYGON, b);
1964
+ p0 = (CIRCLE *)PLRUBY_DFC1(poly_circle, b);
1965
+ if (!p0) return Qnil;
1966
+ res = Data_Make_Struct(pl_cCircle, CIRCLE, pl_circle_mark, free, p1);
1967
+ CPY_FREE(p1, p0, sizeof(CIRCLE));
1968
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1969
+ return res;
1970
+ }
1971
+
1972
+ static VALUE
1973
+ pl_circle_to_poly(VALUE obj, VALUE a)
1974
+ {
1975
+ CIRCLE *b;
1976
+ POLYGON *p0, *p1;
1977
+ VALUE res;
1978
+ int sz0;
1979
+
1980
+ Data_Get_Struct(obj, CIRCLE, b);
1981
+ p0 = (POLYGON *)PLRUBY_DFC2(circle_poly, Int32GetDatum(NUM2INT(a)), b);
1982
+ if (!p0) return Qnil;
1983
+ sz0 = GET_VARSIZE(POLYGON, p0);
1984
+ p1 = (POLYGON *)ALLOC_N(char, sz0);
1985
+ CPY_FREE(p1, p0, sz0);
1986
+ res = Data_Wrap_Struct(pl_cPoly, pl_poly_mark, free, p1);
1987
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
1988
+ return res;
1989
+ }
1990
+
1991
+ static VALUE
1992
+ pl_circle_to_box(VALUE obj)
1993
+ {
1994
+ CIRCLE *b;
1995
+ BOX *p0, *p1;
1996
+ VALUE res;
1997
+
1998
+ Data_Get_Struct(obj, CIRCLE, b);
1999
+ p0 = (BOX *)PLRUBY_DFC1(poly_box, b);
2000
+ if (!p0) return Qnil;
2001
+ res = Data_Make_Struct(pl_cBox, BOX, pl_box_mark, free, p1);
2002
+ CPY_FREE(p1, p0, sizeof(BOX));
2003
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
2004
+ return res;
2005
+ }
2006
+
2007
+ static VALUE
2008
+ pl_point_on(VALUE obj, VALUE a)
2009
+ {
2010
+ Point *p0;
2011
+
2012
+ Data_Get_Struct(obj, Point, p0);
2013
+ if (TYPE(a) != T_DATA) {
2014
+ rb_raise(rb_eArgError, "on : expected a geometry object");
2015
+ }
2016
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
2017
+ return pl_point_eq(obj, a);
2018
+ }
2019
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_lseg_mark) {
2020
+ LSEG *l1;
2021
+
2022
+ Data_Get_Struct(a, LSEG, l1);
2023
+ if (PLRUBY_DFC2(on_ps, p0, l1)) return Qtrue;
2024
+ return Qfalse;
2025
+ }
2026
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_box_mark) {
2027
+ BOX *l1;
2028
+
2029
+ Data_Get_Struct(a, BOX, l1);
2030
+ if (PLRUBY_DFC2(on_pb, p0, l1)) return Qtrue;
2031
+ return Qfalse;
2032
+ }
2033
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_path_mark) {
2034
+ PATH *l1;
2035
+
2036
+ Data_Get_Struct(a, PATH, l1);
2037
+ if (PLRUBY_DFC2(on_ppath, p0, l1)) return Qtrue;
2038
+ return Qfalse;
2039
+ }
2040
+ rb_raise(rb_eArgError, "on : invalid geometry object");
2041
+ return Qnil;
2042
+ }
2043
+
2044
+ static VALUE
2045
+ pl_point_contained(VALUE obj, VALUE a)
2046
+ {
2047
+ Point *p0;
2048
+
2049
+ Data_Get_Struct(obj, Point, p0);
2050
+ if (TYPE(a) != T_DATA) {
2051
+ rb_raise(rb_eArgError, "contained : expected a geometry object");
2052
+ }
2053
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
2054
+ return pl_point_eq(obj, a);
2055
+ }
2056
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_poly_mark) {
2057
+ POLYGON *l1;
2058
+
2059
+ Data_Get_Struct(a, POLYGON, l1);
2060
+ if (PLRUBY_DFC2(pt_contained_poly, p0, l1)) return Qtrue;
2061
+ return Qfalse;
2062
+ }
2063
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_circle_mark) {
2064
+ CIRCLE *l1;
2065
+
2066
+ Data_Get_Struct(a, CIRCLE, l1);
2067
+ if (PLRUBY_DFC2(pt_contained_circle, p0, l1)) return Qtrue;
2068
+ return Qfalse;
2069
+ }
2070
+ rb_raise(rb_eArgError, "contained : invalid geometry object");
2071
+ return Qnil;
2072
+ }
2073
+
2074
+ static VALUE
2075
+ pl_lseg_on(VALUE obj, VALUE a)
2076
+ {
2077
+ LSEG *l0;
2078
+
2079
+ Data_Get_Struct(obj, LSEG, l0);
2080
+ if (TYPE(a) != T_DATA) {
2081
+ rb_raise(rb_eArgError, "on : expected a geometry object");
2082
+ }
2083
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_lseg_mark) {
2084
+ a = pl_lseg_cmp(obj, a);
2085
+ if (NUM2INT(a) == 0) return Qtrue;
2086
+ return Qfalse;
2087
+ }
2088
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_box_mark) {
2089
+ BOX *l1;
2090
+
2091
+ Data_Get_Struct(a, BOX, l1);
2092
+ if (PLRUBY_DFC2(on_sb, l0, l1)) return Qtrue;
2093
+ return Qfalse;
2094
+ }
2095
+ rb_raise(rb_eArgError, "on : invalid geometry object");
2096
+ return Qnil;
2097
+ }
2098
+
2099
+ static VALUE
2100
+ pl_geo_distance(VALUE obj, VALUE a, VALUE b)
2101
+ {
2102
+
2103
+ if (TYPE(a) != T_DATA || TYPE(b) != T_DATA) {
2104
+ rb_raise(rb_eArgError, "distance : expected 2 geometry object");
2105
+ }
2106
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
2107
+ Point *p0;
2108
+
2109
+ Data_Get_Struct(a, Point, p0);
2110
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
2111
+ Point *p1;
2112
+
2113
+ Data_Get_Struct(b, Point, p1);
2114
+ RETURN_FLOAT2(a, b, PLRUBY_DFC2(point_distance, p0, p1));
2115
+ }
2116
+ return pl_geo_distance(obj, b, a);
2117
+ }
2118
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_lseg_mark) {
2119
+ LSEG *l0;
2120
+
2121
+ Data_Get_Struct(a, LSEG, l0);
2122
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
2123
+ Point *p;
2124
+
2125
+ Data_Get_Struct(b, Point, p);
2126
+ RETURN_FLOAT2(a, b, PLRUBY_DFC2(dist_ps, p, l0));
2127
+ }
2128
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_lseg_mark) {
2129
+ LSEG *l1;
2130
+
2131
+ Data_Get_Struct(a, LSEG, l1);
2132
+ RETURN_FLOAT2(a, b, PLRUBY_DFC2(lseg_distance, l0, l1));
2133
+ }
2134
+ return pl_geo_distance(obj, b, a);
2135
+ }
2136
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_box_mark) {
2137
+ BOX *l0;
2138
+
2139
+ Data_Get_Struct(a, BOX, l0);
2140
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
2141
+ Point *p;
2142
+
2143
+ Data_Get_Struct(b, Point, p);
2144
+ RETURN_FLOAT2(a, b, PLRUBY_DFC2(dist_pb, p, l0));
2145
+ }
2146
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_lseg_mark) {
2147
+ LSEG *l1;
2148
+
2149
+ Data_Get_Struct(a, LSEG, l1);
2150
+ RETURN_FLOAT2(a, b, PLRUBY_DFC2(dist_sb, l1, l0));
2151
+ }
2152
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_box_mark) {
2153
+ BOX *l1;
2154
+
2155
+ Data_Get_Struct(b, BOX, l1);
2156
+ RETURN_FLOAT2(a, a, PLRUBY_DFC2(box_distance, l0, l1));
2157
+ }
2158
+ return pl_geo_distance(obj, b, a);
2159
+ }
2160
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_path_mark) {
2161
+ PATH *l0;
2162
+
2163
+ Data_Get_Struct(a, PATH, l0);
2164
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_point_mark) {
2165
+ Point *p;
2166
+
2167
+ Data_Get_Struct(b, Point, p);
2168
+ RETURN_FLOAT2(a, b, PLRUBY_DFC2(dist_ppath, p, l0));
2169
+ }
2170
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_path_mark) {
2171
+ PATH *l1;
2172
+
2173
+ Data_Get_Struct(b, PATH, l1);
2174
+ RETURN_FLOAT2(a, a, PLRUBY_DFC2(path_distance, l0, l1));
2175
+ }
2176
+ }
2177
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_poly_mark) {
2178
+ POLYGON *l0;
2179
+
2180
+ Data_Get_Struct(a, POLYGON, l0);
2181
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_poly_mark) {
2182
+ POLYGON *l1;
2183
+
2184
+ Data_Get_Struct(b, POLYGON, l1);
2185
+ RETURN_FLOAT2(a, a, PLRUBY_DFC2(poly_distance, l0, l1));
2186
+ }
2187
+ }
2188
+ if (RDATA(a)->dmark == (RUBY_DATA_FUNC)pl_circle_mark) {
2189
+ CIRCLE *l0;
2190
+
2191
+ Data_Get_Struct(a, CIRCLE, l0);
2192
+ if (RDATA(b)->dmark == (RUBY_DATA_FUNC)pl_circle_mark) {
2193
+ CIRCLE *l1;
2194
+
2195
+ Data_Get_Struct(b, CIRCLE, l1);
2196
+ RETURN_FLOAT2(a, a, PLRUBY_DFC2(circle_distance, l0, l1));
2197
+ }
2198
+ }
2199
+ rb_raise(rb_eArgError, "distance : invalid geometry objects (%s, %s)",
2200
+ rb_class2name(rb_obj_class(a)), rb_class2name(rb_obj_class(b)));
2201
+ return Qnil;
2202
+ }
2203
+
2204
+ void Init_plruby_geometry()
2205
+ {
2206
+ VALUE pl_cLseg, pl_mGeo;
2207
+
2208
+ pl_mGeo = rb_define_module("Geometry");
2209
+ rb_define_module_function(pl_mGeo, "distance", pl_geo_distance, 2);
2210
+ pl_cPoint = rb_define_class("Point", rb_cObject);
2211
+ rb_undef_method(CLASS_OF(pl_cPoint), "method_missing");
2212
+ #if HAVE_RB_DEFINE_ALLOC_FUNC
2213
+ rb_define_alloc_func(pl_cPoint, pl_point_s_alloc);
2214
+ #else
2215
+ rb_define_singleton_method(pl_cPoint, "allocate", pl_point_s_alloc, 0);
2216
+ #endif
2217
+ rb_define_singleton_method(pl_cPoint, "new", plruby_s_new, -1);
2218
+ rb_define_singleton_method(pl_cPoint, "from_string", pl_point_s_str, 1);
2219
+ rb_define_singleton_method(pl_cPoint, "from_datum", pl_point_s_datum, 1);
2220
+ rb_define_method(pl_cPoint, "to_datum", pl_point_to_datum, 1);
2221
+ rb_define_method(pl_cPoint, "initialize", pl_point_init, 2);
2222
+ #ifndef HAVE_RB_INITIALIZE_COPY
2223
+ rb_define_method(pl_cPoint, "clone", plruby_clone, 0);
2224
+ #endif
2225
+ rb_define_method(pl_cPoint, "initialize_copy", pl_point_init_copy, 1);
2226
+ #if PG_PL_VERSION >= 74
2227
+ rb_define_method(pl_cPoint, "marshal_load", pl_point_mload, 1);
2228
+ rb_define_method(pl_cPoint, "marshal_dump", pl_point_mdump, -1);
2229
+ #ifndef RUBY_CAN_USE_MARSHAL_LOAD
2230
+ rb_define_singleton_method(pl_cPoint, "_load", plruby_s_load, 1);
2231
+ rb_define_alias(pl_cPoint, "_dump", "marshal_dump");
2232
+ #endif
2233
+ #endif
2234
+ rb_define_method(pl_cPoint, "x", pl_point_x, 0);
2235
+ rb_define_method(pl_cPoint, "x=", pl_point_setx, 1);
2236
+ rb_define_method(pl_cPoint, "y", pl_point_y, 0);
2237
+ rb_define_method(pl_cPoint, "y=", pl_point_sety, 1);
2238
+ rb_define_method(pl_cPoint, "[]", pl_point_aref, 1);
2239
+ rb_define_method(pl_cPoint, "[]=", pl_point_aset, 2);
2240
+ rb_define_method(pl_cPoint, "to_s", pl_point_to_s, 0);
2241
+ rb_define_method(pl_cPoint, "+", pl_point_add, 1);
2242
+ rb_define_method(pl_cPoint, "-", pl_point_sub, 1);
2243
+ rb_define_method(pl_cPoint, "*", pl_point_mul, 1);
2244
+ rb_define_method(pl_cPoint, "/", pl_point_div, 1);
2245
+ rb_define_method(pl_cPoint, "left?", pl_point_left, 1);
2246
+ rb_define_method(pl_cPoint, "right?", pl_point_right, 1);
2247
+ rb_define_method(pl_cPoint, "above?", pl_point_above, 1);
2248
+ rb_define_method(pl_cPoint, "below?", pl_point_below, 1);
2249
+ rb_define_method(pl_cPoint, "vertical?", pl_point_vert, 1);
2250
+ rb_define_method(pl_cPoint, "horizontal?", pl_point_horiz, 1);
2251
+ rb_define_method(pl_cPoint, "==", pl_point_eq, 1);
2252
+ rb_define_method(pl_cPoint, "slope", pl_point_slope, 1);
2253
+ rb_define_method(pl_cPoint, "on?", pl_point_on, 1);
2254
+ rb_define_method(pl_cPoint, "in?", pl_point_contained, 1);
2255
+ rb_define_method(pl_cPoint, "contained?", pl_point_contained, 1);
2256
+ pl_cLseg = rb_define_class("Segment", rb_cObject);
2257
+ rb_include_module(pl_cLseg, rb_mComparable);
2258
+ rb_undef_method(CLASS_OF(pl_cLseg), "method_missing");
2259
+ #if HAVE_RB_DEFINE_ALLOC_FUNC
2260
+ rb_define_alloc_func(pl_cLseg, pl_lseg_s_alloc);
2261
+ #else
2262
+ rb_define_singleton_method(pl_cLseg, "allocate", pl_lseg_s_alloc, 0);
2263
+ #endif
2264
+ rb_define_singleton_method(pl_cLseg, "new", plruby_s_new, -1);
2265
+ rb_define_singleton_method(pl_cLseg, "from_string", pl_lseg_s_str, 1);
2266
+ rb_define_singleton_method(pl_cLseg, "from_datum", pl_lseg_s_datum, 1);
2267
+ rb_define_method(pl_cLseg, "to_datum", pl_lseg_to_datum, 1);
2268
+ rb_define_method(pl_cLseg, "initialize", pl_lseg_init, 2);
2269
+ #ifndef HAVE_RB_INITIALIZE_COPY
2270
+ rb_define_method(pl_cLseg, "clone", plruby_clone, 0);
2271
+ #endif
2272
+ rb_define_method(pl_cLseg, "initialize_copy", pl_lseg_init_copy, 1);
2273
+ #if PG_PL_VERSION >= 74
2274
+ rb_define_method(pl_cLseg, "marshal_load", pl_lseg_mload, 1);
2275
+ rb_define_method(pl_cLseg, "marshal_dump", pl_lseg_mdump, -1);
2276
+ #ifndef RUBY_CAN_USE_MARSHAL_LOAD
2277
+ rb_define_singleton_method(pl_cLseg, "_load", plruby_s_load, 1);
2278
+ rb_define_alias(pl_cLseg, "_dump", "marshal_dump");
2279
+ #endif
2280
+ #endif
2281
+ rb_define_method(pl_cLseg, "[]", pl_lseg_aref, 1);
2282
+ rb_define_method(pl_cLseg, "[]=", pl_lseg_aset, 2);
2283
+ rb_define_method(pl_cLseg, "to_s", pl_lseg_to_s, 0);
2284
+ rb_define_method(pl_cLseg, "length", pl_lseg_length, 0);
2285
+ rb_define_method(pl_cLseg, "parallel?", pl_lseg_parallel, 1);
2286
+ rb_define_method(pl_cLseg, "perpendicular?", pl_lseg_perp, 1);
2287
+ rb_define_method(pl_cLseg, "vertical?", pl_lseg_vertical, 0);
2288
+ rb_define_method(pl_cLseg, "horizontal?", pl_lseg_horizontal, 0);
2289
+ rb_define_method(pl_cLseg, "<=>", pl_lseg_cmp, 1);
2290
+ rb_define_method(pl_cLseg, "center", pl_lseg_center, 0);
2291
+ rb_define_method(pl_cLseg, "closest", pl_lseg_closest, 1);
2292
+ rb_define_method(pl_cLseg, "intersect?", pl_lseg_intersect, 1);
2293
+ rb_define_method(pl_cLseg, "intersection", pl_lseg_intersection, 1);
2294
+ rb_define_method(pl_cLseg, "on?", pl_lseg_on, 1);
2295
+ rb_define_method(pl_cLseg, "to_point", pl_lseg_center, 0);
2296
+ pl_cBox = rb_define_class("Box", rb_cObject);
2297
+ rb_include_module(pl_cBox, rb_mComparable);
2298
+ rb_undef_method(CLASS_OF(pl_cBox), "method_missing");
2299
+ #if HAVE_RB_DEFINE_ALLOC_FUNC
2300
+ rb_define_alloc_func(pl_cBox, pl_box_s_alloc);
2301
+ #else
2302
+ rb_define_singleton_method(pl_cBox, "allocate", pl_box_s_alloc, 0);
2303
+ #endif
2304
+ rb_define_singleton_method(pl_cBox, "new", plruby_s_new, -1);
2305
+ rb_define_singleton_method(pl_cBox, "from_string", pl_box_s_str, 1);
2306
+ rb_define_singleton_method(pl_cBox, "from_datum", pl_box_s_datum, 1);
2307
+ rb_define_method(pl_cBox, "to_datum", pl_box_to_datum, 1);
2308
+ rb_define_method(pl_cBox, "initialize", pl_box_init, -1);
2309
+ #ifndef HAVE_RB_INITIALIZE_COPY
2310
+ rb_define_method(pl_cBox, "clone", plruby_clone, 0);
2311
+ #endif
2312
+ rb_define_method(pl_cBox, "initialize_copy", pl_box_init_copy, 1);
2313
+ #if PG_PL_VERSION >= 74
2314
+ rb_define_method(pl_cBox, "marshal_load", pl_box_mload, 1);
2315
+ rb_define_method(pl_cBox, "marshal_dump", pl_box_mdump, -1);
2316
+ #ifndef RUBY_CAN_USE_MARSHAL_LOAD
2317
+ rb_define_singleton_method(pl_cBox, "_load", plruby_s_load, 1);
2318
+ rb_define_alias(pl_cBox, "_dump", "marshal_dump");
2319
+ #endif
2320
+ #endif
2321
+ rb_define_method(pl_cBox, "low", pl_box_low, 0);
2322
+ rb_define_method(pl_cBox, "high", pl_box_high, 0);
2323
+ rb_define_method(pl_cBox, "low=", pl_box_lowset, 1);
2324
+ rb_define_method(pl_cBox, "high=", pl_box_highset, 1);
2325
+ rb_define_method(pl_cBox, "[]", pl_box_aref, 1);
2326
+ rb_define_method(pl_cBox, "[]=", pl_box_aset, 2);
2327
+ rb_define_method(pl_cBox, "to_s", pl_box_to_s, 0);
2328
+ rb_define_method(pl_cBox, "<=>", pl_box_cmp, 1);
2329
+ rb_define_method(pl_cBox, "+", pl_box_add, 1);
2330
+ rb_define_method(pl_cBox, "-", pl_box_sub, 1);
2331
+ rb_define_method(pl_cBox, "*", pl_box_mul, 1);
2332
+ rb_define_method(pl_cBox, "/", pl_box_div, 1);
2333
+ rb_define_method(pl_cBox, "same?", pl_box_same, 1);
2334
+ rb_define_method(pl_cBox, "===", pl_box_same, 1);
2335
+ rb_define_method(pl_cBox, "overlap?", pl_box_overlap, 1);
2336
+ rb_define_method(pl_cBox, "overleft?", pl_box_overleft, 1);
2337
+ rb_define_method(pl_cBox, "left?", pl_box_left, 1);
2338
+ rb_define_method(pl_cBox, "right?", pl_box_right, 1);
2339
+ rb_define_method(pl_cBox, "overright?", pl_box_overright, 1);
2340
+ rb_define_method(pl_cBox, "contained?", pl_box_contained, 1);
2341
+ rb_define_method(pl_cBox, "in?", pl_box_contained, 1);
2342
+ rb_define_method(pl_cBox, "contain?", pl_box_contain, 1);
2343
+ rb_define_method(pl_cBox, "below?", pl_box_below, 1);
2344
+ rb_define_method(pl_cBox, "above?", pl_box_above, 1);
2345
+ rb_define_method(pl_cBox, "area", pl_box_area, 0);
2346
+ rb_define_method(pl_cBox, "width", pl_box_width, 0);
2347
+ rb_define_method(pl_cBox, "height", pl_box_height, 0);
2348
+ rb_define_method(pl_cBox, "center", pl_box_center, 0);
2349
+ rb_define_method(pl_cBox, "closest", pl_box_closest, 1);
2350
+ rb_define_method(pl_cBox, "intersect?", pl_box_intersect, 1);
2351
+ rb_define_method(pl_cBox, "intersection", pl_box_intersection, 1);
2352
+ rb_define_method(pl_cBox, "diagonal", pl_box_diagonal, 0);
2353
+ rb_define_method(pl_cBox, "to_point", pl_box_center, 0);
2354
+ rb_define_method(pl_cBox, "to_segment", pl_box_diagonal, 0);
2355
+ rb_define_method(pl_cBox, "to_lseg", pl_box_diagonal, 0);
2356
+ rb_define_method(pl_cBox, "to_poly", pl_box_to_poly, 0);
2357
+ rb_define_method(pl_cBox, "to_polygon", pl_box_to_poly, 0);
2358
+ rb_define_method(pl_cBox, "to_circle", pl_box_to_circle, 0);
2359
+ pl_cPath = rb_define_class("Path", rb_cObject);
2360
+ rb_include_module(pl_cPath, rb_mComparable);
2361
+ rb_undef_method(CLASS_OF(pl_cPath), "method_missing");
2362
+ #if HAVE_RB_DEFINE_ALLOC_FUNC
2363
+ rb_define_alloc_func(pl_cPath, pl_path_s_alloc);
2364
+ #else
2365
+ rb_define_singleton_method(pl_cPath, "allocate", pl_path_s_alloc, 0);
2366
+ #endif
2367
+ rb_define_singleton_method(pl_cPath, "new", plruby_s_new, -1);
2368
+ rb_define_singleton_method(pl_cPath, "from_string", pl_path_s_str, 1);
2369
+ rb_define_singleton_method(pl_cPath, "from_datum", pl_path_s_datum, 1);
2370
+ rb_define_method(pl_cPath, "to_datum", pl_path_to_datum, 1);
2371
+ rb_define_method(pl_cPath, "initialize", pl_path_init, -1);
2372
+ #ifndef HAVE_RB_INITIALIZE_COPY
2373
+ rb_define_method(pl_cPath, "clone", plruby_clone, 0);
2374
+ #endif
2375
+ rb_define_method(pl_cPath, "initialize_copy", pl_path_init_copy, 1);
2376
+ #if PG_PL_VERSION >= 74
2377
+ rb_define_method(pl_cPath, "marshal_load", pl_path_mload, 1);
2378
+ rb_define_method(pl_cPath, "marshal_dump", pl_path_mdump, -1);
2379
+ #ifndef RUBY_CAN_USE_MARSHAL_LOAD
2380
+ rb_define_singleton_method(pl_cPath, "_load", plruby_s_load, 1);
2381
+ rb_define_alias(pl_cPath, "_dump", "marshal_dump");
2382
+ #endif
2383
+ #endif
2384
+ rb_define_method(pl_cPath, "to_s", pl_path_to_s, 0);
2385
+ rb_define_method(pl_cPath, "<=>", pl_path_cmp, 1);
2386
+ rb_define_method(pl_cPath, "npoints", pl_path_npoints, 0);
2387
+ rb_define_method(pl_cPath, "close", pl_path_close, 0);
2388
+ rb_define_method(pl_cPath, "open", pl_path_open, 0);
2389
+ rb_define_method(pl_cPath, "closed?", pl_path_closed, 0);
2390
+ rb_define_method(pl_cPath, "length", pl_path_length, 0);
2391
+ rb_define_method(pl_cPath, "<<", pl_path_concat, 1);
2392
+ rb_define_method(pl_cPath, "concat", pl_path_concat, 1);
2393
+ rb_define_method(pl_cPath, "+", pl_path_add, 1);
2394
+ rb_define_method(pl_cPath, "-", pl_path_sub, 1);
2395
+ rb_define_method(pl_cPath, "*", pl_path_mul, 1);
2396
+ rb_define_method(pl_cPath, "/", pl_path_div, 1);
2397
+ rb_define_method(pl_cPath, "to_poly", pl_path_to_poly, 0);
2398
+ rb_define_method(pl_cPath, "to_polygon", pl_path_to_poly, 0);
2399
+ #if PG_PL_VERSION >= 75
2400
+ rb_define_method(pl_cPath, "area", pl_path_area, 0);
2401
+ #endif
2402
+ pl_cPoly = rb_define_class("Polygon", rb_cObject);
2403
+ rb_undef_method(CLASS_OF(pl_cPoly), "method_missing");
2404
+ #if HAVE_RB_DEFINE_ALLOC_FUNC
2405
+ rb_define_alloc_func(pl_cPoly, pl_poly_s_alloc);
2406
+ #else
2407
+ rb_define_singleton_method(pl_cPoly, "allocate", pl_poly_s_alloc, 0);
2408
+ #endif
2409
+ rb_define_singleton_method(pl_cPoly, "new", plruby_s_new, -1);
2410
+ rb_define_singleton_method(pl_cPoly, "from_string", pl_poly_s_str, 1);
2411
+ rb_define_singleton_method(pl_cPoly, "from_datum", pl_poly_s_datum, 1);
2412
+ rb_define_method(pl_cPoly, "to_datum", pl_poly_to_datum, 1);
2413
+ rb_define_method(pl_cPoly, "initialize", pl_poly_init, -1);
2414
+ #ifndef HAVE_RB_INITIALIZE_COPY
2415
+ rb_define_method(pl_cPoly, "clone", plruby_clone, 0);
2416
+ #endif
2417
+ rb_define_method(pl_cPoly, "initialize_copy", pl_poly_init_copy, 1);
2418
+ #if PG_PL_VERSION >= 74
2419
+ rb_define_method(pl_cPoly, "marshal_load", pl_poly_mload, 1);
2420
+ rb_define_method(pl_cPoly, "marshal_dump", pl_poly_mdump, -1);
2421
+ #ifndef RUBY_CAN_USE_MARSHAL_LOAD
2422
+ rb_define_singleton_method(pl_cPoly, "_load", plruby_s_load, 1);
2423
+ rb_define_alias(pl_cPoly, "_dump", "marshal_dump");
2424
+ #endif
2425
+ #endif
2426
+ rb_define_method(pl_cPoly, "to_s", pl_poly_to_s, 0);
2427
+ rb_define_method(pl_cPoly, "left?", pl_poly_left, 1);
2428
+ rb_define_method(pl_cPoly, "overleft?", pl_poly_overleft, 1);
2429
+ rb_define_method(pl_cPoly, "right?", pl_poly_right, 1);
2430
+ rb_define_method(pl_cPoly, "overright?", pl_poly_overright, 1);
2431
+ rb_define_method(pl_cPoly, "same?", pl_poly_same, 1);
2432
+ rb_define_method(pl_cPoly, "==", pl_poly_same, 1);
2433
+ rb_define_method(pl_cPoly, "contain?", pl_poly_contain, 1);
2434
+ rb_define_method(pl_cPoly, "contained?", pl_poly_contained, 1);
2435
+ rb_define_method(pl_cPoly, "in?", pl_poly_contained, 1);
2436
+ rb_define_method(pl_cPoly, "overlap?", pl_poly_overlap, 1);
2437
+ rb_define_method(pl_cPoly, "npoints", pl_poly_npoints, 0);
2438
+ rb_define_method(pl_cPoly, "center", pl_poly_center, 0);
2439
+ rb_define_method(pl_cPoly, "to_point", pl_poly_center, 0);
2440
+ rb_define_method(pl_cPoly, "to_path", pl_poly_to_path, 0);
2441
+ rb_define_method(pl_cPoly, "to_box", pl_poly_to_box, 0);
2442
+ rb_define_method(pl_cPoly, "to_circle", pl_poly_to_circle, 0);
2443
+ pl_cCircle = rb_define_class("Circle", rb_cObject);
2444
+ rb_include_module(pl_cCircle, rb_mComparable);
2445
+ rb_undef_method(CLASS_OF(pl_cCircle), "method_missing");
2446
+ #if HAVE_RB_DEFINE_ALLOC_FUNC
2447
+ rb_define_alloc_func(pl_cCircle, pl_circle_s_alloc);
2448
+ #else
2449
+ rb_define_singleton_method(pl_cCircle, "allocate", pl_circle_s_alloc, 0);
2450
+ #endif
2451
+ rb_define_singleton_method(pl_cCircle, "new", plruby_s_new, -1);
2452
+ rb_define_singleton_method(pl_cCircle, "from_string", pl_circle_s_str, 1);
2453
+ rb_define_singleton_method(pl_cCircle, "from_datum", pl_circle_s_datum, 1);
2454
+ rb_define_method(pl_cCircle, "to_datum", pl_circle_to_datum, 1);
2455
+ rb_define_method(pl_cCircle, "initialize", pl_circle_init, 2);
2456
+ #ifndef HAVE_RB_INITIALIZE_COPY
2457
+ rb_define_method(pl_cCircle, "clone", plruby_clone, 0);
2458
+ #endif
2459
+ rb_define_method(pl_cCircle, "initialize_copy", pl_circle_init_copy, 1);
2460
+ #if PG_PL_VERSION >= 74
2461
+ rb_define_method(pl_cCircle, "marshal_load", pl_circle_mload, 1);
2462
+ rb_define_method(pl_cCircle, "marshal_dump", pl_circle_mdump, -1);
2463
+ #ifndef RUBY_CAN_USE_MARSHAL_LOAD
2464
+ rb_define_singleton_method(pl_cCircle, "_load", plruby_s_load, 1);
2465
+ rb_define_alias(pl_cCircle, "_dump", "marshal_dump");
2466
+ #endif
2467
+ #endif
2468
+ rb_define_method(pl_cCircle, "to_s", pl_circle_to_s, 0);
2469
+ rb_define_method(pl_cCircle, "left?", pl_circle_left, 1);
2470
+ rb_define_method(pl_cCircle, "overleft?", pl_circle_overleft, 1);
2471
+ rb_define_method(pl_cCircle, "right?", pl_circle_right, 1);
2472
+ rb_define_method(pl_cCircle, "overright?", pl_circle_overright, 1);
2473
+ rb_define_method(pl_cCircle, "same?", pl_circle_same, 1);
2474
+ rb_define_method(pl_cCircle, "===", pl_circle_same, 1);
2475
+ rb_define_method(pl_cCircle, "contain?", pl_circle_contain, 1);
2476
+ rb_define_method(pl_cCircle, "contained?", pl_circle_contained, 1);
2477
+ rb_define_method(pl_cCircle, "in?", pl_circle_contained, 1);
2478
+ rb_define_method(pl_cCircle, "overlap?", pl_circle_overlap, 1);
2479
+ rb_define_method(pl_cCircle, "below?", pl_circle_below, 1);
2480
+ rb_define_method(pl_cCircle, "above?", pl_circle_above, 1);
2481
+ rb_define_method(pl_cCircle, "<=>", pl_circle_cmp, 1);
2482
+ rb_define_method(pl_cCircle, "+", pl_circle_add, 1);
2483
+ rb_define_method(pl_cCircle, "-", pl_circle_sub, 1);
2484
+ rb_define_method(pl_cCircle, "*", pl_circle_mul, 1);
2485
+ rb_define_method(pl_cCircle, "/", pl_circle_div, 1);
2486
+ rb_define_method(pl_cCircle, "area", pl_circle_area, 0);
2487
+ rb_define_method(pl_cCircle, "radius", pl_circle_radius, 0);
2488
+ rb_define_method(pl_cCircle, "diameter", pl_circle_diameter, 0);
2489
+ rb_define_method(pl_cCircle, "center", pl_circle_center, 0);
2490
+ rb_define_method(pl_cCircle, "to_point", pl_circle_center, 0);
2491
+ rb_define_method(pl_cCircle, "to_poly", pl_circle_to_poly, 1);
2492
+ rb_define_method(pl_cCircle, "to_polygon", pl_circle_to_poly, 1);
2493
+ rb_define_method(pl_cCircle, "to_box", pl_circle_to_box, 0);
2494
+ }