geo 0.1.2
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.
- data/README +24 -0
- data/examples/intersects.rb +26 -0
- data/ext/common.c +35 -0
- data/ext/common.h +97 -0
- data/ext/extconf.rb +51 -0
- data/ext/geo.c +163 -0
- data/ext/geo_set.c +488 -0
- data/ext/geo_set.h +156 -0
- data/ext/intersection.c +58 -0
- data/ext/intersection.h +38 -0
- data/ext/line.c +436 -0
- data/ext/line.h +170 -0
- data/ext/line_set.c +596 -0
- data/ext/line_set.h +87 -0
- data/ext/point.c +265 -0
- data/ext/point.h +123 -0
- data/ext/point_set.c +93 -0
- data/ext/point_set.h +44 -0
- data/ext/triangle.c +412 -0
- data/ext/triangle.h +83 -0
- data/ext/triangle_set.c +347 -0
- data/ext/triangle_set.h +68 -0
- data/ext/types.h +48 -0
- metadata +69 -0
data/ext/intersection.h
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
#ifndef INTERSECTION_H
|
3
|
+
#define INTERSECTION_H
|
4
|
+
|
5
|
+
#include "common.h"
|
6
|
+
|
7
|
+
|
8
|
+
#define INTERSECTION_CLOSEST_POINT(intersection_pointer,point_pointer) ((intersection_pointer)->type == itPOINT ? \
|
9
|
+
(intersection_pointer)->point : \
|
10
|
+
(DISTANCE((intersection_pointer)->line->p1, \
|
11
|
+
(point_pointer)) < DISTANCE((intersection_pointer)->line->p2, \
|
12
|
+
(point_pointer)) ? \
|
13
|
+
(intersection_pointer)->line->p1 : \
|
14
|
+
(intersection_pointer)->line->p2))
|
15
|
+
#define INTERSECTION_DISTANCE(intersection_pointer,point_pointer) ((intersection_pointer)->type == itPOINT ? \
|
16
|
+
DISTANCE((intersection_pointer)->point, (point_pointer)) : \
|
17
|
+
MIN(DISTANCE((intersection_pointer)->line->p1, (point_pointer)), \
|
18
|
+
DISTANCE((intersection_pointer)->line->p2, (point_pointer))))
|
19
|
+
|
20
|
+
|
21
|
+
void
|
22
|
+
free_intersection(Intersection *intersection);
|
23
|
+
|
24
|
+
Intersection*
|
25
|
+
new_intersection_with_line(Line *l, Line *with);
|
26
|
+
|
27
|
+
Intersection *
|
28
|
+
new_intersection_with_point(Point *p, Line *with);
|
29
|
+
|
30
|
+
VALUE
|
31
|
+
rb_intersection(Intersection *intersection, Point *from);
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
#endif
|
data/ext/line.c
ADDED
@@ -0,0 +1,436 @@
|
|
1
|
+
|
2
|
+
#include "common.h"
|
3
|
+
|
4
|
+
VALUE rb_line;
|
5
|
+
|
6
|
+
/*
|
7
|
+
* Dont use this on lines that have been rubified (RB_LINE),
|
8
|
+
* since they will be freed by ruby. Make sure that they have
|
9
|
+
* rubified points (RB_POINT) as well though!
|
10
|
+
*/
|
11
|
+
static void
|
12
|
+
line_free(Line *l) {
|
13
|
+
free(l->p1);
|
14
|
+
free(l->p2);
|
15
|
+
free(l);
|
16
|
+
}
|
17
|
+
|
18
|
+
void
|
19
|
+
line_mark(Line *line) {
|
20
|
+
if (line->p1 != NULL)
|
21
|
+
rb_gc_mark(line->p1->rbPoint);
|
22
|
+
if (line->p2 != NULL)
|
23
|
+
rb_gc_mark(line->p2->rbPoint);
|
24
|
+
}
|
25
|
+
|
26
|
+
Line*
|
27
|
+
new_line_with_points(Point *p1, Point *p2) {
|
28
|
+
Line *rval = ALLOC(Line);
|
29
|
+
rval->p1 = p1;
|
30
|
+
rval->p2 = p2;
|
31
|
+
rval->rbLine = 0;
|
32
|
+
return rval;
|
33
|
+
}
|
34
|
+
|
35
|
+
Line*
|
36
|
+
new_line_with_coordinates(gdouble x1, gdouble y1, gdouble x2, gdouble y2) {
|
37
|
+
Line *rval = ALLOC(Line);
|
38
|
+
rval->p1 = new_point(x1, y1);
|
39
|
+
rval->p2 = new_point(x2, y2);
|
40
|
+
rval->rbLine = 0;
|
41
|
+
return rval;
|
42
|
+
}
|
43
|
+
|
44
|
+
void
|
45
|
+
line_destroy_notify(gpointer l) {
|
46
|
+
line_free((Line *) l);
|
47
|
+
}
|
48
|
+
|
49
|
+
VALUE
|
50
|
+
rb_line_alloc(VALUE class) {
|
51
|
+
Line *l = ALLOC(Line);
|
52
|
+
l->p1 = NULL;
|
53
|
+
l->p2 = NULL;
|
54
|
+
return RB_LINE(l, class);
|
55
|
+
}
|
56
|
+
|
57
|
+
VALUE
|
58
|
+
rb_line_initialize(int argc, VALUE *argv, VALUE self) {
|
59
|
+
Line *l;
|
60
|
+
Point *p1;
|
61
|
+
Point *p2;
|
62
|
+
if (argc == 2) {
|
63
|
+
CHECK_POINT(argv[0]);
|
64
|
+
CHECK_POINT(argv[1]);
|
65
|
+
POINT(argv[0], p1);
|
66
|
+
POINT(argv[1], p2);
|
67
|
+
} else if (argc == 4) {
|
68
|
+
CHECK_NUMERICALITY(argv[0]);
|
69
|
+
CHECK_NUMERICALITY(argv[1]);
|
70
|
+
CHECK_NUMERICALITY(argv[2]);
|
71
|
+
CHECK_NUMERICALITY(argv[3]);
|
72
|
+
p1 = ALLOC(Point);
|
73
|
+
p1->x = NUM2DBL(argv[0]);
|
74
|
+
p1->y = NUM2DBL(argv[1]);
|
75
|
+
p2 = ALLOC(Point);
|
76
|
+
p2->x = NUM2DBL(argv[2]);
|
77
|
+
p2->y = NUM2DBL(argv[3]);
|
78
|
+
RB_POINT(p1, rb_point);
|
79
|
+
RB_POINT(p2, rb_point);
|
80
|
+
} else {
|
81
|
+
rb_raise(rb_eTypeError, "Arguments to %s#new have to be 2 Grueserve::Map::Points or 4 numbers.", rb_obj_classname(self));
|
82
|
+
}
|
83
|
+
LINE(self, l);
|
84
|
+
l->p1 = p1;
|
85
|
+
l->p2 = p2;
|
86
|
+
return self;
|
87
|
+
}
|
88
|
+
|
89
|
+
VALUE
|
90
|
+
rb_line_inspect(VALUE self) {
|
91
|
+
gchar rval[1024];
|
92
|
+
Line *l;
|
93
|
+
LINE(self, l);
|
94
|
+
snprintf(rval, 1024, "<%s:%p p1=<%s:%p x=%f y=%f> p2=<%s:%p x=%f y=%f>>",
|
95
|
+
rb_obj_classname(self), l,
|
96
|
+
rb_obj_classname(l->p1->rbPoint), l->p1, l->p1->x, l->p1->y,
|
97
|
+
rb_obj_classname(l->p2->rbPoint), l->p2, l->p2->x, l->p2->y);
|
98
|
+
return rb_str_new2(rval);
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE
|
102
|
+
rb_line_set_p1(VALUE self, VALUE new_point) {
|
103
|
+
Line *l;
|
104
|
+
Point *p;
|
105
|
+
CHECK_POINT(new_point);
|
106
|
+
LINE(self, l);
|
107
|
+
POINT(new_point, p);
|
108
|
+
l->p1 = p;
|
109
|
+
return new_point;
|
110
|
+
}
|
111
|
+
|
112
|
+
VALUE
|
113
|
+
rb_line_set_p2(VALUE self, VALUE new_point) {
|
114
|
+
Line *l;
|
115
|
+
Point *p;
|
116
|
+
CHECK_POINT(new_point);
|
117
|
+
LINE(self, l);
|
118
|
+
POINT(new_point, p);
|
119
|
+
l->p2 = p;
|
120
|
+
return new_point;
|
121
|
+
}
|
122
|
+
|
123
|
+
VALUE
|
124
|
+
rb_line_p1(VALUE self) {
|
125
|
+
Line *l;
|
126
|
+
LINE(self, l);
|
127
|
+
return l->p1->rbPoint;
|
128
|
+
}
|
129
|
+
|
130
|
+
VALUE
|
131
|
+
rb_line_p2(VALUE self) {
|
132
|
+
Line *l;
|
133
|
+
LINE(self, l);
|
134
|
+
return l->p2->rbPoint;
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* If argument is a point:
|
139
|
+
* Is the point between the endpoints of the line?
|
140
|
+
* If argument is a line:
|
141
|
+
* Is any of the endpoints of the subject within the endpoints of the object?
|
142
|
+
*/
|
143
|
+
VALUE
|
144
|
+
rb_line_within(VALUE self, VALUE arg) {
|
145
|
+
Line *l;
|
146
|
+
Point *p;
|
147
|
+
Line *other;
|
148
|
+
if (CLASS(arg) == rb_point) {
|
149
|
+
LINE(self, l);
|
150
|
+
POINT(arg, p);
|
151
|
+
if (POINT_WITHIN_LINE(l, p)) {
|
152
|
+
return Qtrue;
|
153
|
+
} else {
|
154
|
+
return Qfalse;
|
155
|
+
}
|
156
|
+
} else if (CLASS(arg) == rb_line) {
|
157
|
+
LINE(self, l);
|
158
|
+
LINE(arg, other);
|
159
|
+
if (LINE_WITHIN_LINE(l, other)) {
|
160
|
+
return Qtrue;
|
161
|
+
} else {
|
162
|
+
return Qfalse;
|
163
|
+
}
|
164
|
+
} else {
|
165
|
+
rb_raise(rb_eTypeError, "Argument to %s#within? has to be either Grueserve::Map::Line or Grueserve::Map::Point.", rb_obj_classname(self));
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
/*
|
170
|
+
* If argument is a point:
|
171
|
+
* Is the point outside the rectangle described by the endpoints of the line?
|
172
|
+
* If argument is a line:
|
173
|
+
* Is both of the subjects endpoints outside the rectangle described by the endpoints of the object?
|
174
|
+
*/
|
175
|
+
VALUE
|
176
|
+
rb_line_outside(VALUE self, VALUE arg) {
|
177
|
+
Line *l;
|
178
|
+
Point *p;
|
179
|
+
Line *other;
|
180
|
+
if (CLASS(arg) == rb_point) {
|
181
|
+
LINE(self, l);
|
182
|
+
POINT(arg, p);
|
183
|
+
if (POINT_OUTSIDE_LINE(l, p)) {
|
184
|
+
return Qtrue;
|
185
|
+
} else {
|
186
|
+
return Qfalse;
|
187
|
+
}
|
188
|
+
} else if (CLASS(arg) == rb_line) {
|
189
|
+
LINE(self, l);
|
190
|
+
LINE(arg, other);
|
191
|
+
if (LINE_OUTSIDE_LINE(l, other)) {
|
192
|
+
return Qtrue;
|
193
|
+
} else {
|
194
|
+
return Qfalse;
|
195
|
+
}
|
196
|
+
} else {
|
197
|
+
rb_raise(rb_eTypeError, "Argument to %s#outside? has to be either Grueserve::Map::Line or Grueserve::Map::Point.", rb_obj_classname(self));
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
VALUE
|
202
|
+
rb_line_parallel(VALUE self, VALUE p) {
|
203
|
+
Line *me;
|
204
|
+
Line *rval;
|
205
|
+
Point *point;
|
206
|
+
CHECK_POINT(p);
|
207
|
+
LINE(self, me);
|
208
|
+
POINT(p, point);
|
209
|
+
rval = LINE_PARALLEL(me, point);
|
210
|
+
RB_POINT(rval->p1, CLASS(me->p1->rbPoint));
|
211
|
+
RB_POINT(rval->p2, CLASS(me->p2->rbPoint));
|
212
|
+
return RB_LINE(rval, CLASS(self));
|
213
|
+
}
|
214
|
+
|
215
|
+
gint
|
216
|
+
line_side(Line *me, Point *point) {
|
217
|
+
if (LINE_VERTICAL(me)) {
|
218
|
+
if (DBL_EQL(me->p1->x, point->x)) {
|
219
|
+
return 0;
|
220
|
+
} else if (DBL_EOG(me->p1->x, point->x)) {
|
221
|
+
return 1;
|
222
|
+
} else if (DBL_EOL(me->p1->x, point->x)) {
|
223
|
+
return -1;
|
224
|
+
} else {
|
225
|
+
rb_raise(rb_eRuntimeError, "Weird! A point should be either on, left or right of a line!");
|
226
|
+
}
|
227
|
+
} else {
|
228
|
+
gdouble y = LINE_Y(me, point->x);
|
229
|
+
if (DBL_EQL(y, point->y)) {
|
230
|
+
return 0;
|
231
|
+
} else if (DBL_EOG(y, point->y)) {
|
232
|
+
return -1;
|
233
|
+
} else if (DBL_EOL(y, point->y)) {
|
234
|
+
return 1;
|
235
|
+
} else {
|
236
|
+
rb_raise(rb_eRuntimeError, "Weird! A point should be either on, above or below a line!");
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
/*
|
242
|
+
* See http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
|
243
|
+
*/
|
244
|
+
Intersection*
|
245
|
+
line_intersection(Line *l1, Line *l2) {
|
246
|
+
if (LINE_OUTSIDE_LINE(l1, l2)) {
|
247
|
+
return NULL;
|
248
|
+
} else {
|
249
|
+
gdouble x4_x3 = l2->p2->x - l2->p1->x;
|
250
|
+
gdouble y1_y3 = l1->p1->y - l2->p1->y;
|
251
|
+
gdouble y4_y3 = l2->p2->y - l2->p1->y;
|
252
|
+
gdouble x1_x3 = l1->p1->x - l2->p1->x;
|
253
|
+
gdouble x2_x1 = l1->p2->x - l1->p1->x;
|
254
|
+
gdouble y2_y1 = l1->p2->y - l1->p1->y;
|
255
|
+
gdouble denominator = y4_y3 * x2_x1 - x4_x3 * y2_y1;
|
256
|
+
if (denominator == 0) {
|
257
|
+
gdouble numerator1 = x4_x3 * y1_y3 - y4_y3 * x1_x3;
|
258
|
+
if (numerator1 == 0) {
|
259
|
+
gdouble new_x1 = MAX(MIN(l1->p1->x, l1->p2->x), MIN(l2->p1->x, l2->p2->x));
|
260
|
+
gdouble new_y1 = MAX(MIN(l1->p1->y, l1->p2->y), MIN(l2->p1->y, l2->p2->y));
|
261
|
+
gdouble new_x2 = MIN(MAX(l1->p1->x, l1->p2->x), MAX(l2->p1->x, l2->p2->x));
|
262
|
+
gdouble new_y2 = MIN(MAX(l1->p1->y, l1->p2->y), MAX(l2->p1->y, l2->p2->y));
|
263
|
+
return new_intersection_with_line(new_line_with_coordinates(new_x1, new_y1, new_x2, new_y2), l1);
|
264
|
+
} else {
|
265
|
+
return NULL;
|
266
|
+
}
|
267
|
+
} else {
|
268
|
+
gdouble t1 = (x4_x3 * y1_y3 - y4_y3 * x1_x3) / denominator;
|
269
|
+
gdouble t2 = (x2_x1 * y1_y3 - y2_y1 * x1_x3) / denominator;
|
270
|
+
if (t1 < 0 || t1 > 1 || t2 < 0 || t2 > 1)
|
271
|
+
return NULL;
|
272
|
+
return new_intersection_with_point(new_point(l1->p1->x + t1 * (l1->p2->x - l1->p1->x),
|
273
|
+
l1->p1->y + t1 * (l1->p2->y - l1->p1->y)), l1);
|
274
|
+
}
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
278
|
+
VALUE
|
279
|
+
rb_line_intersection(VALUE self, VALUE other_line) {
|
280
|
+
Line *me;
|
281
|
+
Line *other;
|
282
|
+
CHECK_LINE(other_line);
|
283
|
+
LINE(self, me);
|
284
|
+
LINE(other_line, other);
|
285
|
+
return rb_intersection(line_intersection(me, other), other->p1);
|
286
|
+
}
|
287
|
+
|
288
|
+
VALUE
|
289
|
+
rb_line_dot(VALUE self, VALUE o) {
|
290
|
+
Line *me;
|
291
|
+
Line *line;
|
292
|
+
CHECK_LINE(o);
|
293
|
+
LINE(self, me);
|
294
|
+
LINE(o, line);
|
295
|
+
return rb_float_new(LINE_DOT(line, me));
|
296
|
+
}
|
297
|
+
|
298
|
+
VALUE
|
299
|
+
rb_line_abs(VALUE self) {
|
300
|
+
Line *me;
|
301
|
+
LINE(self, me);
|
302
|
+
return rb_float_new(DISTANCE(me->p1, me->p2));
|
303
|
+
}
|
304
|
+
|
305
|
+
VALUE
|
306
|
+
rb_line_equals(VALUE self, VALUE o) {
|
307
|
+
if (!LINE_P(o)) {
|
308
|
+
return Qfalse;
|
309
|
+
} else {
|
310
|
+
Line *me;
|
311
|
+
Line *other;
|
312
|
+
LINE(self, me);
|
313
|
+
LINE(o, other);
|
314
|
+
if (LINE_EQUALS(me, other)) {
|
315
|
+
return Qtrue;
|
316
|
+
} else {
|
317
|
+
return Qfalse;
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
322
|
+
gint
|
323
|
+
line_cmp(Line *me, Line *other) {
|
324
|
+
gint tmp;
|
325
|
+
gdouble my_length;
|
326
|
+
gdouble other_length;
|
327
|
+
my_length = DISTANCE(me->p1, me->p2);
|
328
|
+
other_length = DISTANCE(other->p1, other->p2);
|
329
|
+
if (my_length != other_length)
|
330
|
+
return CMP(my_length, other_length);
|
331
|
+
else if ((tmp = point_cmp(me->p1, other->p1)) != 0)
|
332
|
+
return tmp;
|
333
|
+
else
|
334
|
+
return point_cmp(me->p2, other->p2);
|
335
|
+
}
|
336
|
+
|
337
|
+
VALUE
|
338
|
+
rb_line_cmp(VALUE self, VALUE o) {
|
339
|
+
if (!LINE_P(o)) {
|
340
|
+
return INT2NUM(CMP(CLASS(self), CLASS(o)));
|
341
|
+
} else {
|
342
|
+
Line *me;
|
343
|
+
Line *other;
|
344
|
+
LINE(self, me);
|
345
|
+
LINE(o, other);
|
346
|
+
return INT2NUM(line_cmp(me, other));
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
VALUE
|
351
|
+
rb_line_reverse(VALUE self) {
|
352
|
+
Line *me;
|
353
|
+
LINE(self, me);
|
354
|
+
return RB_LINE(new_line_with_points(me->p2, me->p1), rb_line);
|
355
|
+
}
|
356
|
+
|
357
|
+
VALUE
|
358
|
+
rb_line_set_angle(VALUE self, VALUE new_angle) {
|
359
|
+
Line *me;
|
360
|
+
gdouble length;
|
361
|
+
gdouble angle;
|
362
|
+
CHECK_NUMERICALITY(new_angle);
|
363
|
+
LINE(self, me);
|
364
|
+
angle = NUM2DBL(new_angle);
|
365
|
+
length = DISTANCE(me->p1, me->p2);
|
366
|
+
while (angle > M_PI * 2)
|
367
|
+
angle -= M_PI * 2;
|
368
|
+
me->p2->x = me->p1->x + length * cos(angle);
|
369
|
+
me->p2->y = me->p1->y + length * sin(angle);
|
370
|
+
return rb_float_new(angle);
|
371
|
+
}
|
372
|
+
|
373
|
+
VALUE
|
374
|
+
rb_line_angle(VALUE self) {
|
375
|
+
Line *me;
|
376
|
+
LINE(self, me);
|
377
|
+
ZERO_DISTANCE_CHECK(me->p1, me->p2);
|
378
|
+
return rb_float_new(LINE_ANGLE(me));
|
379
|
+
}
|
380
|
+
|
381
|
+
VALUE
|
382
|
+
rb_line_set_abs(VALUE self, VALUE new_abs) {
|
383
|
+
Line *me;
|
384
|
+
gdouble ratio;
|
385
|
+
CHECK_NUMERICALITY(new_abs);
|
386
|
+
LINE(self, me);
|
387
|
+
ZERO_DISTANCE_CHECK(me->p1, me->p2);
|
388
|
+
ratio = NUM2DBL(new_abs) / DISTANCE(me->p1, me->p2);
|
389
|
+
me->p2->x = me->p2->x * ratio;
|
390
|
+
me->p2->y = me->p2->y * ratio;
|
391
|
+
return new_abs;
|
392
|
+
}
|
393
|
+
|
394
|
+
VALUE
|
395
|
+
rb_line_clone(VALUE self) {
|
396
|
+
Line *me;
|
397
|
+
Line *rval;
|
398
|
+
LINE(self, me);
|
399
|
+
rval = new_line_with_coordinates(me->p1->x, me->p1->y, me->p2->x, me->p2->y);
|
400
|
+
RB_POINT(rval->p1, CLASS(me->p1->rbPoint));
|
401
|
+
RB_POINT(rval->p2, CLASS(me->p2->rbPoint));
|
402
|
+
return RB_LINE(rval, CLASS(self));
|
403
|
+
}
|
404
|
+
|
405
|
+
VALUE
|
406
|
+
rb_line_side(VALUE self, VALUE p) {
|
407
|
+
Line *me;
|
408
|
+
Point *point;
|
409
|
+
CHECK_POINT(p);
|
410
|
+
LINE(self, me);
|
411
|
+
POINT(p, point);
|
412
|
+
return INT2NUM(line_side(me, point));
|
413
|
+
}
|
414
|
+
|
415
|
+
VALUE
|
416
|
+
rb_line_contains(VALUE self, VALUE p) {
|
417
|
+
Line *me;
|
418
|
+
Point *point;
|
419
|
+
gint side;
|
420
|
+
CHECK_POINT(p);
|
421
|
+
LINE(self,me);
|
422
|
+
POINT(p, point);
|
423
|
+
side = line_side(me, point);
|
424
|
+
if (side == 0) {
|
425
|
+
return Qtrue;
|
426
|
+
} else {
|
427
|
+
return Qfalse;
|
428
|
+
}
|
429
|
+
}
|
430
|
+
|
431
|
+
VALUE
|
432
|
+
rb_line_from_gpointer(gpointer l) {
|
433
|
+
return ( (Line *) l)->rbLine;
|
434
|
+
}
|
435
|
+
|
436
|
+
|
data/ext/line.h
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
|
2
|
+
#ifndef LINE_H
|
3
|
+
#define LINE_H
|
4
|
+
|
5
|
+
#include "common.h"
|
6
|
+
|
7
|
+
extern VALUE rb_line;
|
8
|
+
|
9
|
+
#define RB_LINE(line_pointer,klass) ((line_pointer)->rbLine = Data_Wrap_Struct(klass, line_mark, free, (line_pointer)))
|
10
|
+
#define LINE(rb_line,line_pointer) Data_Get_Struct((rb_line), Line, (line_pointer))
|
11
|
+
#define LINE_ANGLE(me) (ANGLE((me)->p2->x - (me)->p1->x,(me)->p2->y - (me)->p1->y))
|
12
|
+
#define LINE_VERTICAL(line) ((line)->p1->x == (line)->p2->x)
|
13
|
+
#define LINE_Y(line,v) (LINE_VERTICAL((line)) ? \
|
14
|
+
(line)->p1->y : \
|
15
|
+
(line)->p1->y + ((line)->p2->y - (line)->p1->y) * ((v - (line)->p1->x) / ((line)->p2->x - (line)->p1->x)))
|
16
|
+
#define LINE_EQUALS(l1,l2) (POINT_EQUALS((l1)->p1, (l2)->p1) && POINT_EQUALS((l1)->p2, (l2)->p2))
|
17
|
+
/*
|
18
|
+
* Is the point outside the rectangle described by the endpoints of the line?
|
19
|
+
*/
|
20
|
+
#define POINT_OUTSIDE_LINE(l,p) (((DBL_GT((p)->x, (l)->p1->x) && DBL_GT((p)->x, (l)->p2->x)) || \
|
21
|
+
(DBL_LT((p)->x, (l)->p1->x) && DBL_LT((p)->x, (l)->p2->x))) && \
|
22
|
+
((DBL_GT((p)->y, (l)->p1->y) && DBL_GT((p)->y, (l)->p2->y)) || \
|
23
|
+
(DBL_LT((p)->y, (l)->p1->y) && DBL_LT((p)->y, (l)->p2->y))))
|
24
|
+
|
25
|
+
#define POINT_RIGHT_OF_LINE(l,p) (DBL_GT((p)->x, (l)->p1->x) && DBL_GT((p)->x, (l)->p2->x))
|
26
|
+
#define POINT_LEFT_OF_LINE(l,p) (DBL_LT((p)->x, (l)->p1->x) && DBL_LT((p)->x, (l)->p2->x))
|
27
|
+
#define POINT_ABOVE_LINE(l,p) (DBL_LT((p)->y, (l)->p1->y) && DBL_LT((p)->y, (l)->p2->y))
|
28
|
+
#define POINT_BELOW_LINE(l,p) (DBL_GT((p)->y, (l)->p1->y) && DBL_GT((p)->y, (l)->p2->y))
|
29
|
+
#define LINE_RIGHT_OF_LINE(subject,object) (POINT_RIGHT_OF_LINE((object), (subject)->p1) && POINT_RIGHT_OF_LINE((object), (subject)->p2))
|
30
|
+
#define LINE_LEFT_OF_LINE(subject,object) (POINT_LEFT_OF_LINE((object), (subject)->p1) && POINT_LEFT_OF_LINE((object), (subject)->p2))
|
31
|
+
#define LINE_ABOVE_LINE(subject,object) (POINT_ABOVE_LINE((object), (subject)->p1) && POINT_ABOVE_LINE((object), (subject)->p2))
|
32
|
+
#define LINE_BELOW_LINE(subject,object) (POINT_BELOW_LINE((object), (subject)->p1) && POINT_BELOW_LINE((object), (subject)->p2))
|
33
|
+
/*
|
34
|
+
* Is both of the subjects endpoints outside the rectangle described by the endpoints of the object?
|
35
|
+
*/
|
36
|
+
#define LINE_OUTSIDE_LINE(subject,object) (LINE_RIGHT_OF_LINE((subject), (object)) || \
|
37
|
+
LINE_LEFT_OF_LINE((subject), (object)) || \
|
38
|
+
LINE_ABOVE_LINE((subject), (object)) || \
|
39
|
+
LINE_BELOW_LINE((subject), (object)))
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Is the point between the endpoints of the line?
|
43
|
+
*/
|
44
|
+
#define POINT_WITHIN_LINE(line_pointer,point_pointer) (DBL_EOG((point_pointer)->x, MIN((line_pointer)->p1->x, (line_pointer)->p2->x)) && \
|
45
|
+
DBL_EOL((point_pointer)->x, MAX((line_pointer)->p1->x, (line_pointer)->p2->x)) && \
|
46
|
+
DBL_EOG((point_pointer)->y, MIN((line_pointer)->p1->y, (line_pointer)->p2->y)) && \
|
47
|
+
DBL_EOL((point_pointer)->y, MAX((line_pointer)->p1->y, (line_pointer)->p2->y)))
|
48
|
+
|
49
|
+
#define POINT_ON_LINE(line_pointer,point_pointer) (DBL_EQL((point_pointer)->y, LINE_Y((line_pointer), (point_pointer)->x)) && \
|
50
|
+
POINT_WITHIN_LINE((line_pointer), (point_pointer))
|
51
|
+
/*
|
52
|
+
* Is any of the endpoints of the subject within the endpoints of the object?
|
53
|
+
*/
|
54
|
+
#define LINE_WITHIN_LINE(subject,object) (POINT_WITHIN_LINE((subject), (object)->p1) || \
|
55
|
+
POINT_WITHIN_LINE((subject), (object)->p2))
|
56
|
+
#define LINE_DOT(l1,l2) ((((l1)->p2->x - (l1)->p1->x) * ((l2)->p2->x - (l2)->p1->x)) + (((l1)->p2->y - (l1)->p1->y) * ((l2)->p2->y - (l2)->p1->y)))
|
57
|
+
#define POINT_BETWEEN_PARALLEL_LINES(l1,l2,p) ((line_side((l1),(p)) >= 0 && line_side((l2),(p)) <= 0) || \
|
58
|
+
(line_side((l1),(p)) <= 0 && line_side((l2),(p)) >= 0))
|
59
|
+
#define LINE_P(l) (!NIL_P((l)) && rb_is_a((l), rb_line))
|
60
|
+
#define CHECK_LINE(l) if (!LINE_P((l))) rb_raise(rb_eTypeError, "Expected Grueserve::Map::Line!")
|
61
|
+
#define LINE_PARALLEL(l,p) (new_line_with_coordinates((p)->x, (p)->y, (p)->x + (l)->p2->x - (l)->p1->x, (p)->y + (l)->p2->y - (l)->p1->y))
|
62
|
+
#define LINE_BOUNDS(line,bottom_left,top_right) (bottom_left)->x = MIN(line->p1->x, line->p2->x); \
|
63
|
+
(bottom_left)->y = MIN(line->p1->y, line->p2->y); \
|
64
|
+
(top_right)->x = MAX(line->p1->x, line->p2->x); \
|
65
|
+
(top_right)->y = MAX(line->p1->y, line->p2->y)
|
66
|
+
|
67
|
+
void
|
68
|
+
line_mark(Line *line);
|
69
|
+
|
70
|
+
Line*
|
71
|
+
new_line_with_points(Point *p1, Point *p2);
|
72
|
+
|
73
|
+
Line*
|
74
|
+
new_line_with_coordinates(gdouble x1, gdouble y1, gdouble x2, gdouble y2);
|
75
|
+
|
76
|
+
void
|
77
|
+
line_destroy_notify(gpointer l);
|
78
|
+
|
79
|
+
VALUE
|
80
|
+
rb_line_alloc(VALUE class);
|
81
|
+
|
82
|
+
VALUE
|
83
|
+
rb_line_initialize(int argc, VALUE *argv, VALUE self);
|
84
|
+
|
85
|
+
VALUE
|
86
|
+
rb_line_inspect(VALUE self);
|
87
|
+
|
88
|
+
VALUE
|
89
|
+
rb_line_set_p1(VALUE self, VALUE new_point);
|
90
|
+
|
91
|
+
VALUE
|
92
|
+
rb_line_set_p2(VALUE self, VALUE new_point);
|
93
|
+
|
94
|
+
VALUE
|
95
|
+
rb_line_p1(VALUE self);
|
96
|
+
|
97
|
+
VALUE
|
98
|
+
rb_line_p2(VALUE self);
|
99
|
+
|
100
|
+
/*
|
101
|
+
* If argument is a point:
|
102
|
+
* Is the point between the endpoints of the line?
|
103
|
+
* If argument is a line:
|
104
|
+
* Is any of the endpoints of the subject within the endpoints of the object?
|
105
|
+
*/
|
106
|
+
VALUE
|
107
|
+
rb_line_within(VALUE self, VALUE arg);
|
108
|
+
|
109
|
+
/*
|
110
|
+
* If argument is a point:
|
111
|
+
* Is the point outside the rectangle described by the endpoints of the line?
|
112
|
+
* If argument is a line:
|
113
|
+
* Is both of the subjects endpoints outside the rectangle described by the endpoints of the object?
|
114
|
+
*/
|
115
|
+
VALUE
|
116
|
+
rb_line_outside(VALUE self, VALUE arg);
|
117
|
+
|
118
|
+
|
119
|
+
VALUE
|
120
|
+
rb_line_parallel(VALUE self, VALUE p);
|
121
|
+
|
122
|
+
gint
|
123
|
+
line_side(Line *me, Point *point);
|
124
|
+
|
125
|
+
Intersection*
|
126
|
+
line_intersection(Line *l1, Line *l2);
|
127
|
+
|
128
|
+
VALUE
|
129
|
+
rb_line_intersection(VALUE self, VALUE other_line);
|
130
|
+
|
131
|
+
VALUE
|
132
|
+
rb_line_dot(VALUE self, VALUE o);
|
133
|
+
|
134
|
+
VALUE
|
135
|
+
rb_line_abs(VALUE self);
|
136
|
+
|
137
|
+
VALUE
|
138
|
+
rb_line_equals(VALUE self, VALUE o);
|
139
|
+
|
140
|
+
VALUE
|
141
|
+
rb_line_cmp(VALUE self, VALUE o);
|
142
|
+
|
143
|
+
VALUE
|
144
|
+
rb_line_reverse(VALUE self);
|
145
|
+
|
146
|
+
VALUE
|
147
|
+
rb_line_set_angle(VALUE self, VALUE new_angle);
|
148
|
+
|
149
|
+
VALUE
|
150
|
+
rb_line_angle(VALUE self);
|
151
|
+
|
152
|
+
VALUE
|
153
|
+
rb_line_set_abs(VALUE self, VALUE new_abs);
|
154
|
+
|
155
|
+
VALUE
|
156
|
+
rb_line_clone(VALUE self);
|
157
|
+
|
158
|
+
VALUE
|
159
|
+
rb_line_side(VALUE self, VALUE p);
|
160
|
+
|
161
|
+
VALUE
|
162
|
+
rb_line_contains(VALUE self, VALUE p);
|
163
|
+
|
164
|
+
gint
|
165
|
+
line_cmp(Line *me, Line *other);
|
166
|
+
|
167
|
+
VALUE
|
168
|
+
rb_line_from_gpointer(gpointer l);
|
169
|
+
|
170
|
+
#endif
|