📄 ezpolyclip.pas
字号:
edge.bundle[BELOW, SUBJ] );
End;
End;
(* Update parity *)
parity[CLIP] := parity[CLIP] Xor edge.bundle[ABOVE, CLIP];
parity[SUBJ] := parity[SUBJ] Xor edge.bundle[ABOVE, SUBJ];
(* Update horizontal state *)
If boolean( exists[CLIP] ) Then
horiz[CLIP] := next_hstate[ord( horiz[CLIP] ), ( ( exists[CLIP] - 1 ) Shl 1 ) + parity[CLIP]];
If boolean( exists[SUBJ] ) Then
horiz[SUBJ] :=
next_hstate[ord( horiz[SUBJ] ),
( ( exists[SUBJ] - 1 ) Shl 1 ) + parity[SUBJ]];
vclass := tr + ( tl Shl 1 ) + ( br Shl 2 ) + ( bl Shl 3 );
If contributing Then
Begin
xb := edge.xb;
Case TVertexType( vclass ) Of
vtEMN, vtIMN:
Begin
add_local_min( out_poly, edge, xb, yb );
px := xb;
cf := edge.outp[ABOVE];
End;
vtERI:
Begin
If xb <> px Then
Begin
add_right( cf, xb, yb );
px := xb;
End;
edge.outp[ABOVE] := cf;
cf := Nil;
End;
vtELI:
Begin
add_left( edge.outp[BELOW], xb, yb );
px := xb;
cf := edge.outp[BELOW];
End;
vtEMX:
Begin
If xb <> px Then
Begin
add_left( cf, xb, yb );
px := xb;
End;
merge_right( cf, edge.outp[BELOW], out_poly );
cf := Nil;
End;
vtILI:
Begin
If xb <> px Then
Begin
add_left( cf, xb, yb );
px := xb;
End;
edge.outp[ABOVE] := cf;
cf := Nil;
End;
vtIRI:
Begin
add_right( edge.outp[BELOW], xb, yb );
px := xb;
cf := edge.outp[BELOW];
edge.outp[BELOW] := Nil;
End;
vtIMX:
Begin
If xb <> px Then
Begin
add_right( cf, xb, yb );
px := xb;
End;
merge_left( cf, edge.outp[BELOW], out_poly );
cf := Nil;
edge.outp[BELOW] := Nil;
End;
vtIMM:
Begin
If xb <> px Then
Begin
add_right( cf, xb, yb );
px := xb;
End;
merge_left( cf, edge.outp[BELOW], out_poly );
edge.outp[BELOW] := Nil;
add_local_min( out_poly, edge, xb, yb );
cf := edge.outp[ABOVE];
End;
vtEMM:
Begin
If xb <> px Then
Begin
add_left( cf, xb, yb );
px := xb;
End;
merge_right( cf, edge.outp[BELOW], out_poly );
edge.outp[BELOW] := Nil;
add_local_min( out_poly, edge, xb, yb );
cf := edge.outp[ABOVE];
End;
vtLED:
Begin
If edge.bot.y = yb Then
add_left( edge.outp[BELOW], xb, yb );
edge.outp[ABOVE] := edge.outp[BELOW];
px := xb;
End;
vtRED:
Begin
If edge.bot.y = yb Then
add_right( edge.outp[BELOW], xb, yb );
edge.outp[ABOVE] := edge.outp[BELOW];
px := xb;
End;
End; (* End of switch *)
End; (* End of contributing conditional *)
End; (* End of edge exists conditional *)
edge := edge.next;
End; (* End of AET loop *)
(* Delete terminating edges from the AET, otherwise compute xt *)
edge := aet;
While edge <> Nil Do
Begin
If edge.top.y = yb Then
Begin
prev_edge := edge.prev;
next_edge := edge.next;
If prev_edge <> Nil Then
prev_edge.next := next_edge
Else
aet := next_edge;
If next_edge <> Nil Then
next_edge.prev := prev_edge;
(* Copy bundle head state to the adjacent tail edge if required *)
If ( ( edge.bstate[BELOW] = bsBUNDLE_HEAD ) And ( prev_edge <> Nil ) ) And
( prev_edge.bstate[BELOW] = bsBUNDLE_TAIL ) Then
Begin
prev_edge.outp[BELOW] := edge.outp[BELOW];
prev_edge.bstate[BELOW] := bsUNBUNDLED;
If ( prev_edge.prev <> Nil ) And
( prev_edge.prev.bstate[BELOW] = bsBUNDLE_TAIL ) Then
prev_edge.bstate[BELOW] := bsBUNDLE_HEAD;
End;
End
Else
Begin
If edge.top.y = yt Then
edge.xt := edge.top.x
Else
edge.xt := edge.bot.x + edge.dx * ( yt - edge.bot.y );
End;
edge := edge.next;
End;
If scanbeam < sbt_entries Then
Begin
(* === SCANBEAM INTERIOR PROCESSING ============================== *)
build_intersection_table( it, aet, dy );
(* Process each node in the intersection table *)
intersect := it;
While intersect <> Nil Do
Begin
e0 := intersect.ie[0];
e1 := intersect.ie[1];
(* Only generate output for contributing intersections *)
If ( boolean( e0.bundle[ABOVE, CLIP] ) Or boolean( e0.bundle[ABOVE, SUBJ] ) ) And
( boolean( e1.bundle[ABOVE, CLIP] ) Or boolean( e1.bundle[ABOVE, SUBJ] ) ) Then
Begin
p := e0.outp[ABOVE];
q := e1.outp[ABOVE];
ix := intersect.point.x;
iy := intersect.point.y + yb;
ain[CLIP] := integer( ( boolean( e0.bundle[ABOVE, CLIP] ) And Not
boolean( e0.bside[CLIP] ) )
Or ( boolean( e1.bundle[ABOVE, CLIP] ) And boolean( e1.bside[CLIP] ) )
Or ( Not boolean( e0.bundle[ABOVE, CLIP] ) And Not
boolean( e1.bundle[ABOVE, CLIP] )
And boolean( e0.bside[CLIP] ) And boolean( e1.bside[CLIP] ) ) );
ain[SUBJ] := integer( ( boolean( e0.bundle[ABOVE, SUBJ] ) And Not
boolean( e0.bside[SUBJ] ) )
Or ( boolean( e1.bundle[ABOVE, SUBJ] ) And boolean( e1.bside[SUBJ] ) )
Or ( Not boolean( e0.bundle[ABOVE, SUBJ] ) And Not
boolean( e1.bundle[ABOVE, SUBJ] )
And boolean( e0.bside[SUBJ] ) And boolean( e1.bside[SUBJ] ) ) );
(* Determine quadrant occupancies *)
bl := 0;
br := 0;
tl := 0;
tr := 0;
Case op Of
pcDIFF, pcINT:
Begin
tr := ( ain[CLIP] ) And ( ain[SUBJ] );
tl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] )
And ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] );
br := ( ain[CLIP] Xor e0.bundle[ABOVE, CLIP] )
And ( ain[SUBJ] Xor e0.bundle[ABOVE, SUBJ] );
bl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] Xor e0.bundle[ABOVE,
CLIP] )
And ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] Xor e0.bundle[ABOVE,
SUBJ] );
End;
pcXOR:
Begin
tr := ( ain[CLIP] ) Xor ( ain[SUBJ] );
tl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] )
Xor ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] );
br := ( ain[CLIP] Xor e0.bundle[ABOVE, CLIP] )
Xor ( ain[SUBJ] Xor e0.bundle[ABOVE, SUBJ] );
bl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] Xor e0.bundle[ABOVE,
CLIP] )
Xor ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] Xor e0.bundle[ABOVE,
SUBJ] );
End;
pcUNION:
Begin
tr := ( ain[CLIP] ) Or ( ain[SUBJ] );
tl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] )
Or ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] );
br := ( ain[CLIP] Xor e0.bundle[ABOVE, CLIP] )
Or ( ain[SUBJ] Xor e0.bundle[ABOVE, SUBJ] );
bl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] Xor e0.bundle[ABOVE,
CLIP] )
Or ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] Xor e0.bundle[ABOVE,
SUBJ] );
End;
End;
vclass := tr + ( tl Shl 1 ) + ( br Shl 2 ) + ( bl Shl 3 );
Case TVertexType( vclass ) Of
vtEMN:
Begin
add_local_min( out_poly, e0, ix, iy );
e1.outp[ABOVE] := e0.outp[ABOVE];
End;
vtERI:
If p <> Nil Then
Begin
add_right( p, ix, iy );
e1.outp[ABOVE] := p;
e0.outp[ABOVE] := Nil;
End;
vtELI:
If q <> Nil Then
Begin
add_left( q, ix, iy );
e0.outp[ABOVE] := q;
e1.outp[ABOVE] := Nil;
End;
vtEMX:
If ( p <> Nil ) And ( q <> Nil ) Then
Begin
add_left( p, ix, iy );
merge_right( p, q, out_poly );
e0.outp[ABOVE] := Nil;
e1.outp[ABOVE] := Nil;
End;
vtIMN:
Begin
add_local_min( out_poly, e0, ix, iy );
e1.outp[ABOVE] := e0.outp[ABOVE];
End;
vtILI:
If p <> Nil Then
Begin
add_left( p, ix, iy );
e1.outp[ABOVE] := p;
e0.outp[ABOVE] := Nil;
End;
vtIRI:
If q <> Nil Then
Begin
add_right( q, ix, iy );
e0.outp[ABOVE] := q;
e1.outp[ABOVE] := Nil;
End;
vtIMX:
If ( p <> Nil ) And ( q <> Nil ) Then
Begin
add_right( p, ix, iy );
merge_left( p, q, out_poly );
e0.outp[ABOVE] := Nil;
e1.outp[ABOVE] := Nil;
End;
vtIMM:
If ( p <> Nil ) And ( q <> Nil ) Then
Begin
add_right( p, ix, iy );
merge_left( p, q, out_poly );
add_local_min( out_poly, e0, ix, iy );
e1.outp[ABOVE] := e0.outp[ABOVE];
End;
vtEMM:
If ( p <> Nil ) And ( q <> Nil ) Then
Begin
add_left( p, ix, iy );
merge_right( p, q, out_poly );
add_local_min( out_poly, e0, ix, iy );
e1.outp[ABOVE] := e0.outp[ABOVE];
End;
End; (* End of switch *)
End; (* End of contributing intersection conditional *)
(* Swap bundle sides in response to edge crossing *)
If boolean( e0.bundle[ABOVE, CLIP] ) Then
e1.bside[CLIP] := ( 1 - e1.bside[CLIP] );
If boolean( e1.bundle[ABOVE, CLIP] ) Then
e0.bside[CLIP] := ( 1 - e0.bside[CLIP] );
If boolean( e0.bundle[ABOVE, SUBJ] ) Then
e1.bside[SUBJ] := ( 1 - e1.bside[SUBJ] );
If boolean( e1.bundle[ABOVE, SUBJ] ) Then
e0.bside[SUBJ] := ( 1 - e0.bside[SUBJ] );
(* Swap e0 and e1 bundles in the AET *)
prev_edge := e0.prev;
next_edge := e1.next;
If next_edge <> Nil Then
next_edge.prev := e0;
If e0.bstate[ABOVE] = bsBUNDLE_HEAD Then
Begin
search := TRUE;
While ( search ) Do
Begin
prev_edge := prev_edge.prev;
If prev_edge <> Nil Then
Begin
If prev_edge.bstate[ABOVE] <> bsBUNDLE_TAIL Then
search := FALSE;
End
Else
search := FALSE;
End;
End;
If prev_edge = Nil Then
Begin
aet.prev := e1;
e1.next := aet;
aet := e0.next;
End
Else
Begin
prev_edge.next.prev := e1;
e1.next := prev_edge.next;
prev_edge.next := e0.next;
End;
e0.next.prev := prev_edge;
e1.next.prev := e1;
e0.next := next_edge;
intersect := intersect.next;
End; (* End of IT loop*)
(* Prepare for next scanbeam *)
edge := aet;
While edge <> Nil Do
Begin
next_edge := edge.next;
succ_edge := edge.succ;
If ( edge.top.y = yt ) And ( succ_edge <> Nil ) Then
Begin
(* Replace AET edge by its successor *)
succ_edge.outp[BELOW] := edge.outp[ABOVE];
succ_edge.bstate[BELOW] := edge.bstate[ABOVE];
succ_edge.bundle[BELOW, CLIP] := edge.bundle[ABOVE, CLIP];
succ_edge.bundle[BELOW, SUBJ] := edge.bundle[ABOVE, SUBJ];
prev_edge := edge.prev;
If prev_edge <> Nil Then
prev_edge.next := succ_edge
Else
aet := succ_edge;
If next_edge <> Nil Then
next_edge.prev := succ_edge;
succ_edge.prev := prev_edge;
succ_edge.next := next_edge;
End
Else
Begin
(* Update this edge *)
edge.outp[BELOW] := edge.outp[ABOVE];
edge.bstate[BELOW] := edge.bstate[ABOVE];
edge.bundle[BELOW, CLIP] := edge.bundle[ABOVE, CLIP];
edge.bundle[BELOW, SUBJ] := edge.bundle[ABOVE, SUBJ];
edge.xb := edge.xt;
End;
edge.outp[ABOVE] := Nil;
edge := next_edge
End;
End;
End; (* === END OF SCANBEAM PROCESSING ================================== *)
(* Generate result polygon from out_poly *)
result.clear;
result.hole.clear;
tmpcontours := count_contours( out_poly );
If tmpcontours > 0 Then
Begin
c := 0;
poly := out_poly;
While poly <> Nil Do
Begin
npoly := poly.next;
If poly.active <> 0 Then
Begin
contour.NumVertices := poly.active;
GetMem( contour.vertex, contour.NumVertices * sizeof( TEzPoint ) );
fillchar( contour.vertex^, contour.NumVertices * sizeof( TEzPoint ), 0 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -