下面是用Visual C++实现的参数化裁剪算法,它包括3个文件:
1) CyrusBeckClipping.cpp
#include "stdafx.h"
#include "global.h"
#include "CyrusBeck.h"
#include "math.h"

BOOL CyrusBeckClipping(float p1[2],float p2[2],float n[][2],float f[][2],int k,
Point2f *Pbegin, Point2f *Pend)
// P1 and P2 are the end points of the line
// the number of edges for the clipping region is k
// the ni are the k normal vectors
// the fi are the k boundary points,one in each edge
// Pbegin and Pend are the addresses pointing to the end points of the clipped line
// initialize the parameter limits, assuming the entire line is visible
{
//tL,tU are the lower and upper parameter limits
float tL=0;
float tU=1;

//calculate the directrix D
float d[2]; //d is the direction of the line, P2-P1
d[0]=p2[0]-p1[0];
d[1]=p2[1]-p1[1];

//start the main loop
for(int i=0;i<k;i++)
{
//calculate wi,d*ni and wi*ni for this value of i
float w[2]; //wi is the weighting function, P1-fi
int j;
for(j=0;j<2;j++)
w[j]=p1[j]-f[i][j];
float Ddotn=d[0]*n[i][0]+d[1]*n[i][1];
float Wdotn=w[0]*n[i][0]+w[1]*n[i][1];
//is the line a point?
if(fabs(Ddotn) > ZERO)
{
//the line is not a point, calculate t
float t = -1 * Wdotn / Ddotn;
//looking for the upper or the lower limit?
if(Ddotn > 0)
{
//looking for the lower limit
//is t within the range 0 to 1?
if(t > 1)//region entirely right of line
return FALSE;//line trivially invisible-exit
else
tL=max(t,tL);
}
else
{
//looking for the upper limit
//is t within the range 0 to 1?
if(t < 0)//region entirely left of line
return FALSE;//line trivially insivible-exit
else
tU=min(t,tU);
}
}//if(Ddotn != 0)
else//here Ddotn=0
{
if(Wdotn < 0)
{
//the limit is trivially invisible or an invisible
//point abnormal exit from the routine occurs
return FALSE;
}
}
}//for i

//a normal exit from the loop has occurred
//check if the line is in fact invisible
if(tL <= tU)//the=catches a visible corner point
{
Pbegin->x=p1[0]+tL*d[0];
Pbegin->y=p1[1]+tL*d[1];

Pend->x=p1[0]+tU*d[0];
Pend->y=p1[1]+tU*d[1];

return TRUE;
}

return FALSE;
}

BOOL CyrusBeck(CPtrList *pList, Point2f *pOut)
{
//准备参数
float p1[2], p2[2], n[MAXOUTPUT][2], f[MAXOUTPUT][2];
int k;

k=0;
POSITION pos;
for(pos=pList->GetHeadPosition();pos;)
{
Point2f *p=(Point2f *)pList->GetNext(pos);
f[k][0]=p->x;
f[k][1]=p->y;
k++;
}

int pre,next;
for(int i=0; i<k; i++)
{
pre=i-1;
if(pre < 0)
pre += k;
next=i+1;
if(next == k)
next=0;
float z1=(f[next][0]-f[i][0])*(f[pre][1]-f[i][1])-
(f[pre][0]-f[i][0])*(f[next][1]-f[i][1]);

n[i][0]=f[next][1]-f[i][1];
n[i][1]=-(f[next][0]-f[i][0]);
float z2=(f[next][0]-f[i][0])*(n[i][1])-
(n[i][0])*(f[next][1]-f[i][1]);

if(z1*z2 < 0)//异号
{
n[i][0] *= -1;
n[i][1] *= -1;
}
}

p1[0]=pOut[0].x;
p1[1]=pOut[0].y;
p2[0]=pOut[1].x;
p2[1]=pOut[1].y;
return CyrusBeckClipping(p1, p2, n, f, k, &(pOut[2]), &(pOut[3]));
}

2) global.h:
#if !defined(AFX_GLOBAL_H)
#define AFX_GLOBAL_H
typedef enum{Left, Right, Bottom, Top} Edge;
#define N_EDGE 4
typedef struct{float x,y;} Point2f;
typedef struct{int x,y;} Point2i;
#define MAXOUTPUT 200 //输出多边形的最多点数
#endif//AFX_GLOBAL_H

3) CyrusBeck.h
#if !defined(AFX_CyrusBeck_H)
#define AFX_CyrusBeck_H
#define ZERO 0.00001
BOOL CyrusBeck(CPtrList *pList, Point2f *pOut);
#endif