1 /*
2 * Parts Copyright (c) 1999 Martin Kroeker All rights reserved.
3 * (based on code written by Martin Skiba when working for Daveg GmbH,
4 * used here with the permission of Daveg GmbH, Darmstadt,Germany) */
5 /* Clip.C Release : 2.2 Date : 12/09/93 by sk */
6 /*--------------------------------------------------------------------
7 * Clip.C
8 *
9 * Clipping von Geraden in Integerdarstellung nach einen
10 * Mischmasch der Algorythmen von Cohen-Sutherland ( Bereichstests)
11 * und Liang-Barsky ( Durchf�hrung )
12 */
13
14 #include <stdio.h>
15 #include <math.h>
16 #include "clip.h"
17
18
19 #define CLIP_INSIDE 0
20 #define CLIP_RIGHT 1
21 #define CLIP_BELOW 2
22 #define CLIP_ABOVE 4
23 #define CLIP_LEFT 8
24
25 #define ClipSurelyOutside(code1,code2) (code1 & code2)
26 #define ClipFullyInside(code1,code2) (! (code1 | code2 ))
27
ClipAreaCode(double x1,double y1,double x2,double y2,double px,double py)28 static short ClipAreaCode(double x1, double y1,
29 double x2, double y2, double px, double py)
30 {
31 short code = CLIP_INSIDE;
32
33 if (px < x1 - 1.e-3)
34 code |= CLIP_LEFT;
35 else if (px > x2 + 1.e-3)
36 code |= CLIP_RIGHT;
37
38 if (py < y1 - 1.e-3)
39 code |= CLIP_BELOW;
40 else if (py > y2 + 1.e-3)
41 code |= CLIP_ABOVE;
42
43 return code;
44 }
45
ClipWithBorder(double delta,double diff,double * tEnter,double * tLeave)46 static int ClipWithBorder(double delta,
47 double diff, double *tEnter, double *tLeave)
48 {
49 double t;
50 t = diff / delta;
51
52 if (fabs(t) < 1.e-5)
53 return 0;
54 if (delta < 0.0) {
55 if (t > *tLeave)
56 return 0;
57 else if (t > *tEnter)
58 *tEnter = t;
59 } else {
60 if (t < *tEnter)
61 return 0;
62 else if (t < *tLeave)
63 *tLeave = t;
64 }
65 return 1;
66 }
67
68
DtClipLine(double xmin,double ymin,double xmax,double ymax,double * x1,double * y1,double * x2,double * y2)69 short DtClipLine(double xmin, double ymin,
70 double xmax, double ymax,
71 double *x1, double *y1, double *x2, double *y2)
72 {
73 short area_code1, area_code2;
74 double eps;
75
76 eps = 1.e-10;
77 area_code1 = ClipAreaCode(xmin, ymin, xmax, ymax, *x1, *y1);
78 area_code2 = ClipAreaCode(xmin, ymin, xmax, ymax, *x2, *y2);
79
80 if (ClipFullyInside(area_code1, area_code2))
81 return CLIP_DRAW;
82
83 if (ClipSurelyOutside(area_code1, area_code2)) {
84 /* fprintf(stderr,"clipped line from %f %f to %f %f\n",*x1,*y1,*x2,*y2);*/
85 return CLIP_NODRAW;
86 } else {
87 double dx, dy;
88 int dx0, dy0;
89 double tEnter, tLeave;
90 double *tE = &tEnter;
91 double *tL = &tLeave;
92
93 dx = *x2 - *x1;
94 dy = *y2 - *y1;
95 tEnter = 0.0;
96 tLeave = 1.;
97 dx0 = (-eps < dx && dx < eps);
98 dy0 = (-eps < dy && dy < eps);
99
100 if (dx0 || ClipWithBorder(-dx, -(xmin - *x1), tE, tL))
101 if (dy0
102 || ClipWithBorder(dy, (ymax - *y1), tE, tL))
103 if (dx0
104 || ClipWithBorder(dx, (xmax - *x1), tE,
105 tL))
106 if (dy0
107 || ClipWithBorder(-dy,
108 -(ymin -
109 *y1), tE,
110 tL)) {
111 *x2 = *x1 + (tLeave * dx);
112 *y2 = *y1 + (tLeave * dy);
113 *x1 = *x1 + (tEnter * dx);
114 *y1 = *y1 + (tEnter * dy);
115
116 return CLIP_DRAW;
117 }
118 }
119 return CLIP_NODRAW;
120 }
121