1 /* Part of XPCE --- The SWI-Prolog GUI toolkit
2
3 Author: Jan Wielemaker and Anjo Anjewierden
4 E-mail: jan@swi.psy.uva.nl
5 WWW: http://www.swi.psy.uva.nl/projects/xpce/
6 Copyright (c) 1985-2002, University of Amsterdam
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12
13 1. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <h/kernel.h>
36 #include <h/graphics.h>
37 #include <math.h>
38 #ifndef M_PI
39 #define M_PI (3.141593)
40 #endif
41
42 #ifdef MAXFLOAT
43 #define DBL_INFINITE MAXFLOAT
44 #elif defined(HUGE_VAL)
45 #define DBL_INFINITE HUGE_VAL
46 #else
47 #define DBL_INFINITE HUGE
48 #endif
49
50
51 status
initialiseLine(Line ln,Int xa,Int ya,Int xb,Int yb,Name arrows)52 initialiseLine(Line ln, Int xa, Int ya, Int xb, Int yb, Name arrows)
53 { if ( isDefault(xa) ) xa = ZERO;
54 if ( isDefault(ya) ) ya = ZERO;
55 if ( isDefault(xb) ) xb = ZERO;
56 if ( isDefault(yb) ) yb = ZERO;
57
58 assign(ln, start_x, xa);
59 assign(ln, start_y, ya);
60 assign(ln, end_x, xb);
61 assign(ln, end_y, yb);
62
63 initialiseJoint((Joint) ln, ZERO, ZERO, ZERO, ZERO, arrows);
64
65 return requestComputeGraphical(ln, DEFAULT);
66 }
67
68
69 #define area_points(x, y, w, h) { x1 = x; \
70 y1 = y; \
71 x2 = x+w; \
72 x2 += (w>=0 ? -1 : 1); \
73 y2 = y+h; \
74 y2 += (h>=0 ? -1 : 1); \
75 }
76
77 static status
loadLine(Line ln,IOSTREAM * fd,ClassDef def)78 loadLine(Line ln, IOSTREAM *fd, ClassDef def)
79 { TRY(loadSlotsObject(ln, fd, def));
80
81 if ( isNil(ln->start_x) ) /* convert old (pre-4.9.4) line */
82 { Area a = ln->area; /* representation */
83 int x = valInt(a->x);
84 int y = valInt(a->y);
85 int w = valInt(a->w);
86 int h = valInt(a->h);
87 int x1, y1, x2, y2;
88
89 area_points(x, y, w, h);
90 assign(ln, start_x, toInt(x1));
91 assign(ln, start_y, toInt(y1));
92 assign(ln, end_x, toInt(x2));
93 assign(ln, end_y, toInt(y2));
94 }
95
96 succeed;
97 }
98
99
100 status
adjustFirstArrowLine(Line ln)101 adjustFirstArrowLine(Line ln)
102 { if ( notNil(ln->first_arrow) )
103 { Any av[4];
104
105 av[0] = ln->start_x;
106 av[1] = ln->start_y;
107 av[2] = ln->end_x;
108 av[3] = ln->end_y;
109
110 if ( qadSendv(ln->first_arrow, NAME_points, 4, av) )
111 { assign(ln->first_arrow, displayed, ON);
112
113 return ComputeGraphical(ln->first_arrow);
114 }
115 }
116
117 fail;
118 }
119
120
121 status
adjustSecondArrowLine(Line ln)122 adjustSecondArrowLine(Line ln)
123 { if ( notNil(ln->second_arrow) )
124 { Any av[4];
125
126 av[0] = ln->end_x;
127 av[1] = ln->end_y;
128 av[2] = ln->start_x;
129 av[3] = ln->start_y;
130
131 if ( qadSendv(ln->second_arrow, NAME_points, 4, av) )
132 { assign(ln->second_arrow, displayed, ON);
133
134 return ComputeGraphical(ln->second_arrow);
135 }
136 }
137
138 fail;
139 }
140
141
142 status
computeLine(Line ln)143 computeLine(Line ln)
144 { if ( notNil(ln->request_compute) )
145 { int x1 = valInt(ln->start_x);
146 int x2 = valInt(ln->end_x);
147 int y1 = valInt(ln->start_y);
148 int y2 = valInt(ln->end_y);
149 int pen = valInt(ln->pen);
150 int x, y, w, h;
151 Area a = ln->area;
152
153 if ( x1 < x2 )
154 { x = x1;
155 w = x2-x1;
156 } else
157 { x = x2;
158 w = x1-x2;
159 }
160 if ( y1 < y2 )
161 { y = y1;
162 h = y2-y1;
163 } else
164 { y = y2;
165 h = y1-y2;
166 }
167
168 if ( pen == 1 )
169 { w++;
170 h++;
171 } else if ( pen > 1 )
172 { int ex = (h > 0 ? (pen*h)/(w+h) : 0); /* h = 0: horizontal line */
173 int ey = (w > 0 ? (pen*w)/(w+h) : 0); /* w = 0: vertical line */
174 int hx = ex/2;
175 int hy = ey/2;
176
177 x -= hx;
178 w += ex;
179 y -= hy;
180 h += ey;
181 }
182
183 if ( ln->selected == ON ) /* should be solved elsewhere */
184 { x -= 3;
185 y -= 3;
186 w += 6;
187 h += 6;
188 }
189
190 CHANGING_GRAPHICAL(ln,
191 assign(a, x, toInt(x));
192 assign(a, y, toInt(y));
193 assign(a, w, toInt(w));
194 assign(a, h, toInt(h));
195
196 if ( adjustFirstArrowLine(ln) )
197 unionNormalisedArea(a, ln->first_arrow->area);
198 if ( adjustSecondArrowLine(ln) )
199 unionNormalisedArea(a, ln->second_arrow->area);
200
201 changedEntireImageGraphical(ln));
202
203 assign(ln, request_compute, NIL);
204 }
205
206 succeed;
207 }
208
209
210 status
copyLine(Line l1,Line l2)211 copyLine(Line l1, Line l2)
212 { copyJoint((Joint) l1, (Joint) l2);
213
214 assign(l1, start_x, l2->start_x);
215 assign(l1, start_y, l2->start_y);
216 assign(l1, end_x, l2->end_x);
217 assign(l1, end_y, l2->end_y);
218
219 succeed;
220 }
221
222
223 static status
RedrawAreaLine(Line ln,Area a)224 RedrawAreaLine(Line ln, Area a)
225 { int x, y, w, h;
226 int x1 = valInt(ln->start_x);
227 int x2 = valInt(ln->end_x);
228 int y1 = valInt(ln->start_y);
229 int y2 = valInt(ln->end_y);
230 int pen = valInt(ln->pen);
231
232 initialiseDeviceGraphical(ln, &x, &y, &w, &h);
233
234 if ( pen != 0 )
235 { r_thickness(pen);
236 r_dash(ln->texture);
237 r_line(x1, y1, x2, y2);
238 }
239
240 if ( adjustFirstArrowLine(ln) )
241 RedrawArea(ln->first_arrow, a);
242 if ( adjustSecondArrowLine(ln) )
243 RedrawArea(ln->second_arrow, a);
244
245 return RedrawAreaGraphical(ln, a);
246 }
247
248
249 status
paintSelectedLine(Line ln)250 paintSelectedLine(Line ln) /* assumes device is initialised! */
251 { r_complement(valInt(ln->start_x)-2, valInt(ln->start_y)-2, 5, 5);
252 r_complement(valInt(ln->end_x)-2, valInt(ln->end_y)-2, 5, 5);
253
254 succeed;
255 }
256
257
258 static status
geometryLine(Line ln,Int x,Int y,Int w,Int h)259 geometryLine(Line ln, Int x, Int y, Int w, Int h)
260 { int needcompute = FALSE;
261 Int dx = ZERO, dy = ZERO;
262
263 if ( notDefault(w) )
264 { assign(ln, end_x, add(ln->start_x, w));
265 needcompute++;
266 }
267 if ( notDefault(h) )
268 { assign(ln, end_y, add(ln->start_y, h));
269 needcompute++;
270 }
271
272 if ( notDefault(x) )
273 { dx = sub(x, ln->area->x);
274 assign(ln, start_x, add(ln->start_x, dx));
275 assign(ln, end_x, add(ln->end_x, dx));
276 }
277 if ( notDefault(y) )
278 { dy = sub(y, ln->area->y);
279 assign(ln, start_y, add(ln->start_y, dy));
280 assign(ln, end_y, add(ln->end_y, dy));
281 }
282
283 CHANGING_GRAPHICAL(ln,
284 if ( needcompute )
285 requestComputeGraphical(ln, DEFAULT);
286 else
287 { Area a = ln->area;
288
289 assign(a, x, add(a->x, dx));
290 assign(a, y, add(a->y, dy));
291 changedEntireImageGraphical(ln);
292 });
293
294 succeed;
295 }
296
297
298 static status
startLine(Line ln,Point pos)299 startLine(Line ln, Point pos)
300 { return pointsLine(ln, pos->x, pos->y, DEFAULT, DEFAULT);
301 }
302
303
304 static status
endLine(Line ln,Point pos)305 endLine(Line ln, Point pos)
306 { return pointsLine(ln, DEFAULT, DEFAULT, pos->x, pos->y);
307 }
308
309
310 static status
startXLine(Line ln,Int x)311 startXLine(Line ln, Int x)
312 { return pointsLine(ln, x, DEFAULT, DEFAULT, DEFAULT);
313 }
314
315
316 static status
startYLine(Line ln,Int y)317 startYLine(Line ln, Int y)
318 { return pointsLine(ln, DEFAULT, y, DEFAULT, DEFAULT);
319 }
320
321
322 static status
endXLine(Line ln,Int x)323 endXLine(Line ln, Int x)
324 { return pointsLine(ln, DEFAULT, DEFAULT, x, DEFAULT);
325 }
326
327
328 static status
endYLine(Line ln,Int y)329 endYLine(Line ln, Int y)
330 { return pointsLine(ln, DEFAULT, DEFAULT, DEFAULT, y);
331 }
332
333
334 static Point
getStartLine(Line ln)335 getStartLine(Line ln)
336 { answer(answerObject(ClassPoint, ln->start_x, ln->start_y, EAV));
337 }
338
339
340 static Point
getEndLine(Line ln)341 getEndLine(Line ln)
342 { answer(answerObject(ClassPoint, ln->end_x, ln->end_y, EAV));
343 }
344
345
346 status
pointsLine(Line ln,Int sx,Int sy,Int ex,Int ey)347 pointsLine(Line ln, Int sx, Int sy, Int ex, Int ey)
348 { if ( !isDefault(sx) ) assign(ln, start_x, sx);
349 if ( !isDefault(sy) ) assign(ln, start_y, sy);
350 if ( !isDefault(ex) ) assign(ln, end_x, ex);
351 if ( !isDefault(ey) ) assign(ln, end_y, ey);
352
353 return requestComputeGraphical(ln, DEFAULT);
354 }
355
356
357 static status
resizeLine(Line ln,Real xfactor,Real yfactor,Point origin)358 resizeLine(Line ln, Real xfactor, Real yfactor, Point origin)
359 { float xf, yf;
360 int ox = valInt(ln->area->x);
361 int oy = valInt(ln->area->y);
362
363 init_resize_graphical(ln, xfactor, yfactor, origin, &xf, &yf, &ox, &oy);
364 if ( xf != 1.0 || yf != 1.0 )
365 { int x1, y1, x2, y2;
366
367 x1 = ox + rfloat((float) (valInt(ln->start_x)-ox) * xf);
368 x2 = ox + rfloat((float) (valInt(ln->end_x)-ox) * xf);
369 y1 = oy + rfloat((float) (valInt(ln->start_y)-oy) * yf);
370 y2 = oy + rfloat((float) (valInt(ln->end_y)-oy) * yf);
371
372 assign(ln, start_x, toInt(x1));
373 assign(ln, start_y, toInt(y1));
374 assign(ln, end_x, toInt(x2));
375 assign(ln, end_y, toInt(y2));
376
377 return requestComputeGraphical(ln, DEFAULT);
378 }
379
380 succeed;
381 }
382
383
384 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
385 int distanceLineToPoint()
386
387 Calculate the distance between the infinite extended line through (x1,
388 y1) and (x2, y2) to the point (px, py) or, if extended is 0, the
389 distance to the line-segment between the two points.
390 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
391
392 static int
dist(int x1,int y1,int x2,int y2)393 dist(int x1, int y1, int x2, int y2)
394 { double dx = (double)(x2-x1);
395 double dy = (double)(y2-y1);
396
397 return rfloat(sqrt(dx*dx+dy*dy));
398 }
399
400
401 int
distanceLineToPoint(int x1,int y1,int x2,int y2,int px,int py,int extended)402 distanceLineToPoint(int x1, int y1, int x2, int y2, int px, int py,
403 int extended)
404 { float a;
405
406 if ( y1 == y2 )
407 { if ( extended )
408 { return abs(y1 - py);
409 } else
410 { if ( x1 < x2 )
411 { if ( px < x1 )
412 return dist(x1, y1, px, py);
413 else if ( px > x2 )
414 return dist(x2, y2, px, py);
415 else
416 return abs(y1 - py);
417 } else
418 { if ( px < x2 )
419 return dist(x2, y2, px, py);
420 else if ( px > x1 )
421 return dist(x1, y1, px, py);
422 else
423 return abs(y1 - py);
424 }
425 }
426 }
427
428 if ( x1 == x2 )
429 { if ( extended )
430 { return abs(x1 - px);
431 } else
432 { if ( y1 < y2 )
433 { if ( py < y1 )
434 return dist(x1, y1, px, py);
435 else if ( py > y2 )
436 return dist(x2, y2, px, py);
437 else
438 return abs(x1 - px);
439 } else
440 { if ( py < y2 )
441 return dist(x2, y2, px, py);
442 else if ( py > y1 )
443 return dist(x1, y1, px, py);
444 else
445 return abs(x1 - px);
446 }
447 }
448 }
449
450 a = ((float)(y2 - y1)) / ((float)(x2 - x1));
451
452 if ( !extended )
453 { int xproj = rfloat((px - a*(float)(y1-py)+a*a*(float)x1)/(1.0+a*a));
454
455 /*Cprintf("Xproj = %d\n", xproj);*/
456
457 if ( x1 < x2 )
458 { if ( xproj < x1 )
459 return dist(x1, y1, px, py);
460 else if ( xproj > x2 )
461 return dist(x2, y2, px, py);
462 else
463 goto not_extended;
464 } else
465 { if ( xproj < x2 )
466 return dist(x2, y2, px, py);
467 else if ( xproj > x1 )
468 return dist(x1, y1, px, py);
469 else
470 goto not_extended;
471 }
472 }
473
474 not_extended:
475 return abs(rfloat((((float)(px - x1)) * a + ((float)(y1 - py))) /
476 sqrt(1.0 + a*a)));
477 }
478
479
480 static status
inEventAreaLine(Line ln,Int x,Int y)481 inEventAreaLine(Line ln, Int x, Int y)
482 { int d;
483 static int evtol = -1;
484
485 if ( evtol < 0 )
486 { Int v = getClassVariableValueObject(ln, NAME_eventTolerance);
487 evtol = (v ? valInt(v) : 5);
488 }
489
490 d = distanceLineToPoint(valInt(ln->start_x), valInt(ln->start_y),
491 valInt(ln->end_x), valInt(ln->end_y),
492 valInt(x), valInt(y), FALSE);
493 if ( d < evtol )
494 succeed;
495
496 fail;
497 }
498
499
500 static Int
getDistanceLine(Line ln,Any obj,BoolObj segment)501 getDistanceLine(Line ln, Any obj, BoolObj segment)
502 { if ( instanceOfObject(obj, ClassEvent) && notNil(ln->device) )
503 { if ( !(obj = getPositionEvent((EventObj) obj, (Graphical) ln->device)) )
504 fail;
505 }
506
507 if ( instanceOfObject(obj, ClassPoint) )
508 { Point pt = obj;
509 int extended = (segment != OFF);
510
511 answer(toInt(distanceLineToPoint(valInt(ln->start_x), valInt(ln->start_y),
512 valInt(ln->end_x), valInt(ln->end_y),
513 valInt(pt->x), valInt(pt->y), extended)));
514 } else
515 { Graphical gr2 = obj;
516
517 answer(getDistanceArea(ln->area, gr2->area));
518 }
519 }
520
521
522
523 static Int
getLengthLine(Line ln)524 getLengthLine(Line ln)
525 { int dx = valInt(ln->end_x) - valInt(ln->start_x);
526 int dy = valInt(ln->end_y) - valInt(ln->start_y);
527
528 answer(toInt(isqrt(dx*dx + dy*dy)));
529 }
530
531
532 static void
parms_line(Line ln,int * a,double * b)533 parms_line(Line ln, int *a, double *b) /* y = a + bx */
534 { int x1 = valInt(ln->start_x);
535 int x2 = valInt(ln->end_x);
536 int y1 = valInt(ln->start_y);
537 int y2 = valInt(ln->end_y);
538
539 if ( x1 == x2 )
540 { *b = DBL_INFINITE; /* vertical */
541 *a = 0;
542 } else
543 { *b = (double)(y2 - y1) / (double)(x2 - x1);
544 *a = y1 - rfloat(*b * (double)x1);
545 }
546
547 DEBUG(NAME_intersection, Cprintf("%d,%d --> %d,%d: y = %d + %2fx\n",
548 x1, y1, x2, y2, *a, *b));
549 }
550
551
552 Point
getIntersectionLine(Line l1,Line l2)553 getIntersectionLine(Line l1, Line l2)
554 { double b1, b2;
555 int a1, a2;
556 double xx;
557 int xy;
558
559 parms_line(l1, &a1, &b1);
560 parms_line(l2, &a2, &b2);
561
562 if ( b1 == b2 )
563 fail; /* parallel */
564 if ( b1 == DBL_INFINITE ) /* l1 is vertical */
565 { xx = (double) valInt(l1->end_x);
566 xy = a2 + rfloat(b2 * xx);
567 } else if ( b2 == DBL_INFINITE ) /* l2 is vertical */
568 { xx = (double) valInt(l2->end_x);
569 xy = a1 + rfloat(b1 * xx);
570 } else
571 { xx = (double)(a2 - a1) / (b1 - b2);
572 xy = a1 + rfloat(b1 * xx);
573 }
574
575 answer(answerObject(ClassPoint, toInt(rfloat(xx)), toInt(xy), EAV));
576 }
577
578
579 Real
getAngleLine(Line ln,Point p)580 getAngleLine(Line ln, Point p)
581 { int x1 = valInt(ln->start_x);
582 int x2 = valInt(ln->end_x);
583 int y1 = valInt(ln->start_y);
584 int y2 = valInt(ln->end_y);
585 double angle;
586 int rte = 0; /* relative-to-end */
587
588 if ( notDefault(p) &&
589 get_distance_point(p, x2, y2) < get_distance_point(p, x1, y1) )
590 rte++;
591
592 if ( rte )
593 angle = atan2((double)(y2-y1), (double)(x1-x2));
594 else
595 angle = atan2((double)(y1-y2), (double)(x2-x1));
596 if ( angle < 0 )
597 angle = 2.0 * M_PI + angle;
598
599 angle = (angle * 180.0) / M_PI;
600
601 answer(CtoReal(angle));
602 }
603
604
605 static status
normaliseLine(Line ln)606 normaliseLine(Line ln)
607 { succeed;
608 }
609
610
611 static status
orientationLine(Line ln,Name o)612 orientationLine(Line ln, Name o)
613 { succeed;
614 }
615
616
617 static status
penLine(Line ln,Int pen)618 penLine(Line ln, Int pen)
619 { if ( ln->pen != pen )
620 { assign(ln, pen, pen);
621
622 return requestComputeGraphical(ln, DEFAULT);
623 }
624
625 succeed;
626 }
627
628
629 /*******************************
630 * CLASS DECLARATION *
631 *******************************/
632
633 /* Type declarations */
634
635 static char *T_points[] =
636 { "start_x=[int]", "start_y=[int]", "end_x=[int]", "end_y=[int]" };
637 static char *T_initialise[] =
638 { "start_x=[int]", "start_y=[int]", "end_x=[int]", "end_y=[int]", "arrows=[{none,first,second,both}]" };
639 static char *T_resize[] =
640 { "factor_x=real", "factor_y=[real]", "origin=[point]" };
641 static char *T_geometry[] =
642 { "x=[int]", "y=[int]", "width=[int]", "height=[int]" };
643 static char *T_distance[] =
644 { "to=graphical|point|event", "segment=[bool]" };
645
646 /* Instance Variables */
647
648 vardecl var_line[] =
649 { SV(NAME_startX, "int", IV_GET|IV_STORE, startXLine,
650 NAME_tip, "X of start-point"),
651 SV(NAME_startY, "int", IV_GET|IV_STORE, startYLine,
652 NAME_tip, "Y of start-point"),
653 SV(NAME_endX, "int", IV_GET|IV_STORE, endXLine,
654 NAME_tip, "X of end-point"),
655 SV(NAME_endY, "int", IV_GET|IV_STORE, endYLine,
656 NAME_tip, "Y of end-point")
657 };
658
659
660 /* Send Methods */
661
662 static senddecl send_line[] =
663 { SM(NAME_initialise, 5, T_initialise, initialiseLine,
664 DEFAULT, "Create line (X1,Y1) - (X2,Y2) with arrows"),
665 SM(NAME_normalise, 0, NULL, normaliseLine,
666 DEFAULT, "Redefined from graphical: no-op"),
667 SM(NAME_orientation, 1, "{north_west,south_west,north_east,south_east}", orientationLine,
668 DEFAULT, "Redefined from graphical: no-op"),
669 SM(NAME_compute, 0, NULL, computeLine,
670 NAME_update, "Update <-area of the line"),
671 SM(NAME_geometry, 4, T_geometry, geometryLine,
672 NAME_resize, "Define start and vector"),
673 SM(NAME_copy, 1, "line", copyLine,
674 NAME_copy, "Copy attributes from other line"),
675 SM(NAME_DrawPostScript, 1, "{head,body}", drawPostScriptLine,
676 NAME_postscript, "Create PostScript"),
677 SM(NAME_end, 1, "point", endLine,
678 NAME_tip, "Set end-point of line segment"),
679 SM(NAME_points, 4, T_points, pointsLine,
680 NAME_tip, "Reconfigure line (X1,Y1) - (X2,Y2)"),
681 SM(NAME_start, 1, "point", startLine,
682 NAME_tip, "Set start-point of line segment"),
683 SM(NAME_resize, 3, T_resize, resizeLine,
684 NAME_area, "Resize line with specified factor"),
685 SM(NAME_pen, 1, "0..", penLine,
686 NAME_appearance, "Thickness of drawing pen")
687 };
688
689 /* Get Methods */
690
691 static getdecl get_line[] =
692 { GM(NAME_angle, 1, "degrees=real", "origin=[point]", getAngleLine,
693 NAME_calculate, "Angle"),
694 GM(NAME_intersection, 1, "point", "with=line", getIntersectionLine,
695 NAME_calculate, "Intersection between both infinitely extended lines"),
696 GM(NAME_length, 0, "int", NULL, getLengthLine,
697 NAME_calculate, "Distance between start and end-points"),
698 GM(NAME_distance, 2, "int", T_distance, getDistanceLine,
699 NAME_calculate, "Distance between areas or to point"),
700 GM(NAME_end, 0, "point", NULL, getEndLine,
701 NAME_tip, "New point representing end-point"),
702 GM(NAME_start, 0, "point", NULL, getStartLine,
703 NAME_tip, "New point representing start-point")
704 };
705
706 /* Resources */
707
708 static classvardecl rc_line[] =
709 { RC(NAME_selectionHandles, RC_REFINE, "line",
710 NULL)
711 };
712
713 /* Class Declaration */
714
715 static Name line_termnames[] =
716 { NAME_startX, NAME_startY, NAME_endX, NAME_endY, NAME_arrows };
717
718 ClassDecl(line_decls,
719 var_line, send_line, get_line, rc_line,
720 5, line_termnames,
721 "$Rev$");
722
723
724 status
makeClassLine(Class class)725 makeClassLine(Class class)
726 { declareClass(class, &line_decls);
727
728 setRedrawFunctionClass(class, RedrawAreaLine);
729 setInEventAreaFunctionClass(class, inEventAreaLine);
730 setLoadStoreFunctionClass(class, loadLine, NULL);
731
732 succeed;
733 }
734