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