Private Sub Clip(plgn As Polygon, p() As punkt, lowerhalf As Boolean)
'
'*********************************************************
'This subroutine takes a general polygon (may be concave)
'and clips it by a straight line
'The boolean variable "lowerhalf" selects which half is
'to be clipped
'
'The polygon must not intersect itself (the code does not
'allow for this possibility, though it shouldn't be too
'difficult to add some checking code to the calling program)
'
'The algorithm has been developed from that outlined in
'the book: "Algorithms for Graphics and Image Processing"
'by Theo Pavlidis (Computer Science Press, 1982)
'ISBN: 0-914894-65-X
'*********************************************************
'
Dim A As Single, B As Single, C As Single
Dim U1 As Single, U2 As Single
Dim i As Integer, j As Integer, k As Integer
Dim k0 As Integer, jcumm As Integer
'Initial value of n (n will vary as the polygon is being clipped)
Dim nini As Integer
Dim kold As Integer
Dim u As Single, v As Single
Dim xa As Single, ya As Single, wa As Single, cro As Single
Dim intr As punkt
Dim auxpol As Polygon
'Array of pointers to the next vertex of the polygon
'Initially, nxt(i) = i+1 for all i (except nxt(plgn.n) = 1) but
'as the clipping operation proceeds it will have to be updated
Dim nxt() As Integer
Dim tempo() As Integer
Dim dumbo As Integer
Dim thesign As Integer
Dim dummy() As Single, dumdum As Single
Dim zeichen As Integer
'Keep a copy of the initial number of vertices
nini = plgn.n
'Initialize the array nxt
ReDim nxt(1 To plgn.n)
For i = 1 To plgn.n
Select Case i
Case plgn.n
nxt(i) = 1
Case Else
nxt(i) = i + 1
End Select
Next
'Straight line equation:
'Ax + By + C = 0
'Calculate the parameters A, B and C from the
'coordinates of both ends of the line segment
If p(1).X = p(2).X Then
'Vertical line
A = 1
B = 0
C = -p(1).X
Else
'Any other slope
A = (p(2).Y - p(1).Y) / (p(2).X - p(1).X)
B = -1
C = p(1).Y - A * p(1).X
End If
'Assign the value of the parameter zeichen
'according to which of the 2 halves of the
'the polygon is to be clipped
If lowerhalf Then
zeichen = 1
Else
zeichen = -1
End If
'For the first vertex of the polygon, calculate the quantity U1
'which represents its position relative to the line:
'If U1>o the point lies below the line (or at its left side if
'the line is vertical)
'If U1 is negative the point is located above it (or to the right)
U1 = A * plgn.vertex(1).X + B * plgn.vertex(1).Y + C
If U1 * zeichen <= 0 Then nxt(1) = 0
'Loop over the other sides of the polygon
For i = 2 To plgn.n
'Calculate the position of vertex i
U2 = A * plgn.vertex(i).X + B * plgn.vertex(i).Y + C
'Check the position of the previous vertex and of the current vertex
If U1 * zeichen <= 0 And U2 * zeichen <= 0 Then
'Set the current vertex pointer to 0 if both vertices
'are located on the side to be clipped
nxt(i) = 0
Else
'Either the vertices are on the opposite sides or
'both lie on the side opposite to that to be clipped
If U1 * zeichen < 0 Or U2 * zeichen < 0 Then
'If on opposite sides, calculate the coordinates of the
'interception between the line and the polygon side from
'the previous vertex to the current one
u = plgn.vertex(i - 1).X - plgn.vertex(i).X
v = plgn.vertex(i - 1).Y - plgn.vertex(i).Y
cro = plgn.vertex(i - 1).X * plgn.vertex(i).Y - plgn.vertex(i - 1).Y * plgn.vertex(i).X
xa = -(u * C + B * cro)
ya = -(v * C - A * cro)
wa = v * B + u * A
If wa <> 0 Then
'Coordinates of the interception
intr.X = xa / wa
intr.Y = ya / wa
Else
MsgBox "Error"
Exit Sub
End If
'The interception point is to be counted as a new
'point, so increment the total number of points
plgn.n = plgn.n + 1
ReDim Preserve plgn.vertex(1 To plgn.n)
ReDim Preserve nxt(1 To plgn.n)
plgn.vertex(plgn.n).X = intr.X
plgn.vertex(plgn.n).Y = intr.Y
If U1 * zeichen < 0 Then
'If the first point is on the side to be clipped
'(the second point is on the opposite side) then
'set its pointer to point to the second point
nxt(plgn.n) = i
Else
'Otherwise, set the previous point's pointer to point
'to the interception point and the second point's
'pointer to zero (as it lies on the side to be clipped)
nxt(i - 1) = plgn.n
nxt(i) = 0
nxt(plgn.n) = 0
End If
End If
'Set the current second vertex as the first
'for the comparison in the next loop
U1 = U2
End If
Next