1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 // Liang-Barsky clipping
18 //----------------------------------------------------------------------------
19 #ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
20 #define AGG_CLIP_LIANG_BARSKY_INCLUDED
22 #include "agg_basics.h"
27 //------------------------------------------------------------------------
30 clipping_flags_x1_clipped
= 4,
31 clipping_flags_x2_clipped
= 1,
32 clipping_flags_y1_clipped
= 8,
33 clipping_flags_y2_clipped
= 2,
34 clipping_flags_x_clipped
= clipping_flags_x1_clipped
| clipping_flags_x2_clipped
,
35 clipping_flags_y_clipped
= clipping_flags_y1_clipped
| clipping_flags_y2_clipped
38 //----------------------------------------------------------clipping_flags
39 // Determine the clipping code of the vertex according to the
40 // Cyrus-Beck line clipping algorithm
45 // -------+--------+-------- clip_box.y2
49 // -------+--------+-------- clip_box.y1
53 // clip_box.x1 clip_box.x2
57 inline unsigned clipping_flags(T x
, T y
, const rect_base
<T
>& clip_box
)
59 return (x
> clip_box
.x2
) |
60 ((y
> clip_box
.y2
) << 1) |
61 ((x
< clip_box
.x1
) << 2) |
62 ((y
< clip_box
.y1
) << 3);
65 //--------------------------------------------------------clipping_flags_x
67 inline unsigned clipping_flags_x(T x
, const rect_base
<T
>& clip_box
)
69 return (x
> clip_box
.x2
) | ((x
< clip_box
.x1
) << 2);
73 //--------------------------------------------------------clipping_flags_y
75 inline unsigned clipping_flags_y(T y
, const rect_base
<T
>& clip_box
)
77 return ((y
> clip_box
.y2
) << 1) | ((y
< clip_box
.y1
) << 3);
81 //-------------------------------------------------------clip_liang_barsky
83 inline unsigned clip_liang_barsky(T x1
, T y1
, T x2
, T y2
,
84 const rect_base
<T
>& clip_box
,
87 const double nearzero
= 1e-30;
89 double deltax
= x2
- x1
;
90 double deltay
= y2
- y1
;
106 // bump off of the vertical
107 deltax
= (x1
> clip_box
.x1
) ? -nearzero
: nearzero
;
112 // bump off of the horizontal
113 deltay
= (y1
> clip_box
.y1
) ? -nearzero
: nearzero
;
140 tinx
= (xin
- x1
) / deltax
;
141 tiny
= (yin
- y1
) / deltay
;
167 toutx
= (xout
- x1
) / deltax
;
168 touty
= (yout
- y1
) / deltay
;
170 tout1
= (toutx
< touty
) ? toutx
: touty
;
172 if(tin2
> 0.0 || tout1
> 0.0)
181 *y
++ = (T
)(y1
+ tinx
* deltay
);
185 *x
++ = (T
)(x1
+ tiny
* deltax
);
196 *y
++ = (T
)(y1
+ toutx
* deltay
);
200 *x
++ = (T
)(x1
+ touty
* deltax
);
232 //----------------------------------------------------------------------------
234 bool clip_move_point(T x1
, T y1
, T x2
, T y2
,
235 const rect_base
<T
>& clip_box
,
236 T
* x
, T
* y
, unsigned flags
)
240 if(flags
& clipping_flags_x_clipped
)
246 bound
= (flags
& clipping_flags_x1_clipped
) ? clip_box
.x1
: clip_box
.x2
;
247 *y
= (T
)(double(bound
- x1
) * (y2
- y1
) / (x2
- x1
) + y1
);
251 flags
= clipping_flags_y(*y
, clip_box
);
252 if(flags
& clipping_flags_y_clipped
)
258 bound
= (flags
& clipping_flags_y1_clipped
) ? clip_box
.y1
: clip_box
.y2
;
259 *x
= (T
)(double(bound
- y1
) * (x2
- x1
) / (y2
- y1
) + x1
);
265 //-------------------------------------------------------clip_line_segment
266 // Returns: ret >= 4 - Fully clipped
267 // (ret & 1) != 0 - First point has been moved
268 // (ret & 2) != 0 - Second point has been moved
271 unsigned clip_line_segment(T
* x1
, T
* y1
, T
* x2
, T
* y2
,
272 const rect_base
<T
>& clip_box
)
274 unsigned f1
= clipping_flags(*x1
, *y1
, clip_box
);
275 unsigned f2
= clipping_flags(*x2
, *y2
, clip_box
);
284 if((f1
& clipping_flags_x_clipped
) != 0 &&
285 (f1
& clipping_flags_x_clipped
) == (f2
& clipping_flags_x_clipped
))
291 if((f1
& clipping_flags_y_clipped
) != 0 &&
292 (f1
& clipping_flags_y_clipped
) == (f2
& clipping_flags_y_clipped
))
304 if(!clip_move_point(tx1
, ty1
, tx2
, ty2
, clip_box
, x1
, y1
, f1
))
308 if(*x1
== *x2
&& *y1
== *y2
)
316 if(!clip_move_point(tx1
, ty1
, tx2
, ty2
, clip_box
, x2
, y2
, f2
))
320 if(*x1
== *x2
&& *y1
== *y2
)