home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1994 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1994.iso
/
netsrcs
/
lng_bars.txt
< prev
next >
Wrap
Internet Message Format
|
1987-03-23
|
8KB
From sbw@naucse.UUCP Mon Mar 23 13:30:21 1987
Path: seismo!rutgers!sri-unix!hplabs!hao!noao!arizona!naucse!sbw
From: sbw@naucse.UUCP (Steve Wampler)
Newsgroups: net.sources
Subject: Liang-Barsky Polygon Clipping (2 C versions)
Message-ID: <270@naucse.UUCP>
Date: 23 Mar 87 18:30:21 GMT
Organization: Northern Arizona University, Flagstaff, Arizona
Lines: 294
The following C functions are two versions of the Liang-Barsky
polygon clipping algorithm. The first is directly from their
paper in CACM (and the corrigenda that followed). The second
is slightly modified and seems to run about 6% quicker (assuming
floating point hardware).
#___________cut mark
/* Liang-Barsky Polygon Clipping [CACM, Vol 26 (Nov, 1983)]
* (with corrections from [CACM (April, 1984)])
*/
/* Note that this assumes the last point == the first in the
* polygon representation the code in the article adds the
* last point in at the start of the algorithm (probably
* a better approach).
*/
/* The following include brings in some macro definitions
* for accessing information about a polygon:
*
* NPNTS() is the number of vertices in the polygon
* (counting first point twice)
*
* GETPNT() accesses the specified point out of the
* polygon.
*
* XCOORD/YCOORD() access the x(y)-coordinate in a point
*
* Macros were used because this code must ultimately tie
* into my wife's animation package, and I don't know
* how she is going to represent polygons yet.
*/
# include "pln.h"
# define INFINITY (1.0e+30)
/* add a new vertex into the output polygon */
# define add(x,y) {\
XCOORD(GETPNT(npoly,npnt)) = x;\
YCOORD(GETPNT(npoly,npnt)) = y;\
++npnt;\
}
/* window bounds (xleft,ybottom), (xright,ytop) */
extern float wx1,wy1, wx2,wy2;
/* The Liang-Barsky Polygon Clipping Algorithm */
fclip(opoly,npoly)
PLN *opoly, *npoly;
{
register int i, npnt;
float deltax, deltay, xin,xout, yin,yout;
float tinx,tiny, toutx,touty, tin1, tin2, tout1,tout2;
float x1,y1, x2,y2;
npnt = 0;
for (i = 0; i < NPNTS(opoly)-1; ++i) {
x1 = XCOORD(GETPNT(opoly,i));
y1 = YCOORD(GETPNT(opoly,i));
x2 = XCOORD(GETPNT(opoly,i+1));
y2 = YCOORD(GETPNT(opoly,i+1));
deltax = x2-x1;
deltay = y2-y1;
if (deltax > 0 || (deltax == 0 && x1>wx2)) { /* points to right */
xin = wx1;
xout = wx2;
}
else {
xin = wx2;
xout = wx1;
}
if (deltay > 0 || (deltay == 0 && y1>wy2)) { /* points up */
yin = wy1;
yout = wy2;
}
else {
yin = wy2;
yout = wy1;
}
tinx = (deltax != 0) ? ((xin - x1)/deltax) : -INFINITY ;
tiny = (deltay != 0) ? ((yin - y1)/deltay) : -INFINITY ;
if (tinx < tiny) { /* hits x first */
tin1 = tinx;
tin2 = tiny;
}
else /* hits y first */
{
tin1 = tiny;
tin2 = tinx;
}
if (1 >= tin1) {
if (0 < tin1) {
add(xin,yin);
}
if (1 >= tin2) {
if (deltax != 0) toutx = (xout-x1)/deltax;
else {
if (wx1 <= x1 && x1 <= wx2) toutx = INFINITY;
else toutx = -INFINITY;
}
if (deltay != 0) touty = (yout-y1)/deltay;
else {
if (wy1 <= y1 && y1 <= wy2) touty = INFINITY;
else touty = -INFINITY;
}
tout1 = (toutx < touty) ? toutx : touty ;
if (0 < tin2 || 0 < tout1) {
if (tin2 <= tout1) {
if (0 < tin2) {
if (tinx > tiny) {
add (xin, y1+tinx*deltay);
}
else {
add (x1 + tiny*deltax, yin);
}
}
if (1 > tout1) {
if (toutx < touty) {
add (xout, y1+toutx*deltay);
}
else {
add (x1 + touty*deltax, yout);
}
}
else {
add (x2,y2);
}
}
else {
if (tinx > tiny) {
add (xin, yout);
}
else {
add (xout, yin);
}
}
}
}
}
}
if (npnt) {
add(XCOORD(GETPNT(npoly,0)),YCOORD(GETPNT(npoly,0)));
}
NPNTS(npoly) = npnt;
}
#___________ cut mark
/* Modified Liang-Barsky Polygon Clipping [CACM, Vol 26 (Nov, 1983)] */
/* see the comments at the start of the unmodified version for more
* details.
*/
# include "pln.h"
# define INFINITY (1.0e+30)
# define NEARZERO (1.0e-30) /* 1/INFINITY */
# define add(x,y) {\
XCOORD(GETPNT(npoly,npnt)) = x;\
YCOORD(GETPNT(npoly,npnt)) = y;\
++npnt;\
}
extern float wx1,wy1, wx2,wy2; /* window boundaries */
fclip(opoly,npoly)
PLN *opoly, *npoly;
{
register int i, npnt;
float deltax, deltay, xin,xout, yin,yout;
float tinx,tiny, toutx,touty, tin1, tin2, tout1,tout2;
float x1,y1, x2,y2;
npnt = 0;
for (i = 0; i < NPNTS(opoly)-1; ++i) {
x1 = XCOORD(GETPNT(opoly,i));
y1 = YCOORD(GETPNT(opoly,i));
x2 = XCOORD(GETPNT(opoly,i+1));
y2 = YCOORD(GETPNT(opoly,i+1));
deltax = x2-x1;
if (deltax == 0) { /* bump off of the vertical */
deltax = (x1 > wx1) ? -NEARZERO : NEARZERO ;
}
deltay = y2-y1;
if (deltay == 0) { /* bump off of the horizontal */
deltay = (y1 > wy1) ? -NEARZERO : NEARZERO ;
}
if (deltax > 0) { /* points to right */
xin = wx1;
xout = wx2;
}
else {
xin = wx2;
xout = wx1;
}
if (deltay > 0) { /* points up */
yin = wy1;
yout = wy2;
}
else {
yin = wy2;
yout = wy1;
}
tinx = (xin - x1)/deltax;
tiny = (yin - y1)/deltay;
if (tinx < tiny) { /* hits x first */
tin1 = tinx;
tin2 = tiny;
}
else /* hits y first */
{
tin1 = tiny;
tin2 = tinx;
}
if (1 >= tin1) {
if (0 < tin1) {
add(xin,yin);
}
if (1 >= tin2) {
toutx = (xout - x1)/deltax;
touty = (yout - y1)/deltay;
tout1 = (toutx < touty) ? toutx : touty ;
if (0 < tin2 || 0 < tout1) {
if (tin2 <= tout1) {
if (0 < tin2) {
if (tinx > tiny) {
add (xin, y1+tinx*deltay);
}
else {
add (x1 + tiny*deltax, yin);
}
}
if (1 > tout1) {
if (toutx < touty) {
add (xout, y1+toutx*deltay);
}
else {
add (x1 + touty*deltax, yout);
}
}
else {
add (x2,y2);
}
}
else {
if (tinx > tiny) {
add (xin, yout);
}
else {
add (xout, yin);
}
}
}
}
}
}
if (npnt) {
add(XCOORD(GETPNT(npoly,0)),YCOORD(GETPNT(npoly,0)));
}
NPNTS(npoly) = npnt;
}
#_________ cut mark
-Steve Wampler
{...}!arizona!naucse!sbw