/* ptinpoly.c - point in polygon inside/outside code.
by Eric Haines, 3D/Eye Inc, erich@eye.com
This code contains the following algorithms:
crossings - count the crossing made by a ray from the test point
crossings-multiply - as above, but avoids a division; often a bit faster
angle summation - sum the angle formed by point and vertex pairs
weiler angle summation - sum the angles using quad movements
half-plane testing - test triangle fan using half-space planes
barycentric coordinates - test triangle fan w/barycentric coords
spackman barycentric - preprocessed barycentric coordinates
trapezoid testing - bin sorting algorithm
grid testing - grid imposed on polygon
exterior test - for convex polygons, check exterior of polygon
inclusion test - for convex polygons, use binary search for edge.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ptinpoly.h"
#define X 0
#define Y 1
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef HUGE
#define HUGE 1.797693134862315e+308
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/* test if a & b are within epsilon. Favors cases where a < b */
#define Near(a,b,eps) ( ((b)-(eps)<(a)) && ((a)-(eps)<(b)) )
#define MALLOC_CHECK( a ) if ( !(a) ) { \
fprintf( stderr, "out of memory\n" ) ; \
exit(1) ; \
}
/* ======= Crossings algorithm ============================================ */
/* Shoot a test ray along +X axis. The strategy, from MacMartin, is to
* compare vertex Y values to the testing point's Y and quickly discard
* edges which are entirely to one side of the test ray.
*
* Input 2D polygon _pgon_ with _numverts_ number of vertices and test point
* _point_, returns 1 if inside, 0 if outside. WINDING and CONVEX can be
* defined for this test.
*/
int CrossingsTest( pgon, numverts, point )
double pgon[][2] ;
int numverts ;
double point[2] ;
{
#ifdef WINDING
register int crossings ;
#endif
register int j, yflag0, yflag1, inside_flag, xflag0 ;
register double ty, tx, *vtx0, *vtx1 ;
#ifdef CONVEX
register int line_flag ;
#endif
tx = point[X] ;
ty = point[Y] ;
vtx0 = pgon[numverts-1] ;
/* get test bit for above/below X axis */
yflag0 = ( vtx0[Y] >= ty ) ;
vtx1 = pgon[0] ;
#ifdef WINDING
crossings = 0 ;
#else
inside_flag = 0 ;
#endif
#ifdef CONVEX
line_flag = 0 ;
#endif
for ( j = numverts+1 ; --j ; ) {
yflag1 = ( vtx1[Y] >= ty ) ;
/* check if endpoints straddle (are on opposite sides) of X axis
* (i.e. the Y's differ); if so, +X ray could intersect this edge.
*/
if ( yflag0 != yflag1 ) {
xflag0 = ( vtx0[X] >= tx ) ;
/* check if endpoints are on same side of the Y axis (i.e. X's
* are the same); if so, it's easy to test if edge hits or misses.
*/
if ( xflag0 == ( vtx1[X] >= tx ) ) {
/* if edge's X values both right of the point, must hit */
#ifdef WINDING
if ( xflag0 ) crossings += ( yflag0 ? -1 : 1 ) ;
#else
if ( xflag0 ) inside_flag = !inside_flag ;
#endif
} else {
/* compute intersection of pgon segment with +X ray, note
* if >= point's X; if so, the ray hits it.
*/
if ( (vtx1[X] - (vtx1[Y]-ty)*
( vtx0[X]-vtx1[X])/(vtx0[Y]-vtx1[Y])) >= tx ) {
#ifdef WINDING
crossings += ( yflag0 ? -1 : 1 ) ;
#else
inside_flag = !inside_flag ;
#endif
}
}
#ifdef CONVEX
/* if this is second edge hit, then done testing */
if ( line_flag ) goto Exit ;
/* note that one edge has been hit by the ray's line */
line_flag = TRUE ;
#endif
}
/* move to next pair of vertices, retaining info as possible */
yflag0 = yflag1 ;
vtx0 = vtx1 ;
vtx1 += 2 ;
}
#ifdef CONVEX
Exit: ;
#endif
#ifdef WINDING
/* test if crossings is not zero */
inside_flag = (crossings != 0) ;
#endif
return( inside_flag ) ;
}
/* ======= Angle summation algorithm ======================================= */
/* Sum angles made by (vtxN to test point to vtxN+1), check if in proper
* range to be inside. VERY SLOW, included for tutorial reasons (i.e.
* to show why one should never use this algorithm).
*
* Input 2D polygon _pgon_ with _numverts_ number of vertices and test point
* _point_, returns 1 if inside, 0 if outside.
*/
int AngleTest( pgon, numverts, point )
double pgon[][2] ;
int numverts ;
double point[2] ;
{
register double *vtx0, *vtx1, angle, len, vec0[2], vec1[2], vec_dot ;
register int j ;
int inside_flag ;
/* sum the angles and see if answer mod 2*PI > PI */
vtx0 = pgon[numverts-1] ;
vec0[X] = vtx0[X] - point[X] ;
vec0[Y] = vtx0[Y] - point[Y] ;
len = sqrt( vec0[X] * vec0[X] + vec0[Y] * vec0[Y] ) ;
if ( len <= 0.0 ) {
/* point and vertex coincide */
return( 1 ) ;
}
vec0[X] /= len ;
vec0[Y] /= len ;
angle = 0.0 ;
for ( j = 0 ; j < numverts ; j++ ) {
vtx1 = pgon[j] ;
vec1[X] = vtx1[X] - point[X] ;
vec1[Y] = vtx1[Y] - point[Y] ;
len = sqrt( vec1[X] * vec1[X] + vec1[Y] * vec1[Y] ) ;
if ( len <= 0.0 ) {
/* point and vertex coincide */
return( 1 ) ;
}
vec1[X] /= len ;
vec1[Y] /= len ;
/* check if vec1 is to "left" or "right" of vec0 */
vec_dot = vec0[X] * vec1[X] + vec0[Y] * vec1[Y] ;
if ( vec_dot < -1.0 ) {
/* point is on edge, so always add 180 degrees. always
* adding is not necessarily the right answer for
* concave polygons and subtractive triangles.
*/
angle += M_PI ;
} else if ( vec_dot < 1.0 ) {
if ( vec0[X] * vec1[Y] - vec1[X] * vec0[Y] >= 0.0 ) {
/* add angle due to dot product of vectors */
angle += acos( vec_dot ) ;
} else {
/* subtract angle due to dot product of vectors */
angle -= acos( vec_dot ) ;
}
} /* if vec_dot >= 1.0, angle does not change */
/* get to next point */
vtx0 = vtx1 ;
vec0[X] = vec1[X] ;
vec0[Y] = vec1[Y] ;
}
/* test if between PI and 3*PI, 5*PI and 7*PI, etc */
inside_flag = fmod( fabs(angle) + M_PI, 4.0*M_PI ) > 2.0*M_PI ;
return( inside_flag ) ;
}
/* ======= Weiler algorithm ============================================ */
/* Track quadrant movements using Weiler's algorithm (elsewhere in Graphics
* Gems IV). Algorithm has been optimized for testing purposes, but the
* crossings algorithm is still faster. Included to provide timings.
*
* Input 2D polygon _pgon_ with _numverts_ number of vertices and test point
* _point_, returns 1 if inside, 0 if outside. WINDING can be defined for
* this test.
*/
#define QUADRANT( vtx, x, y ) \
(((vtx)[X]>(x)) ? ( ((vtx)[Y]>(y)) ? 0:3 ) : ( ((vtx)[Y]>(y)) ? 1:2 ))
#define X_INTERCEPT( v0, v1, y ) \
( (((v1)[X]-(v0)[X])/((v1)[Y]-(v0)[Y])) * ((y)-(v0)[Y]) + (v0)[X] )
int WeilerTest( pgon, numverts, point )
double pgon[][2] ;
int numverts ;
double point[2] ;
{
register int angle, qd, next_qd, delta, j ;
register double ty, tx, *vtx0, *vtx1 ;
int inside_flag ;
tx = point[X] ;
ty = point[Y] ;
vtx0 = pgon[numverts-1] ;
qd = QUADRANT( vtx0, tx, ty ) ;
angle = 0 ;
vtx1 = pgon[0] ;
for ( j = numverts+1 ; --j ; ) {
/* calculate quadrant and delta from last quadrant */
next_qd = QUADRANT( vtx1, tx, ty ) ;
delta = next_qd - qd ;
/* adjust delta and add it to total angle sum */
switch ( delta ) {
case 0: /* do nothing */
break ;
case -1:
case 3:
angle-- ;
qd = next_qd ;
break ;
case 1:
case -3:
angle++ ;
qd = next_qd ;
break ;
case 2:
case -2:
if (X_INTERCEPT( vtx0, vtx1, ty ) > tx ) {
angle -= delta ;
} else {
angle += delta ;
}
qd = next_qd ;
break ;
}
/* increment for next step */
vtx0 = vtx1 ;
vtx1 += 2 ;
}
#ifdef WINDING
/* simple windings test: if angle != 0, then point is inside */
inside_flag = ( angle != 0 ) ;
#else
/* Jordan test: if angle is +-4, 12, 20, etc then point is inside */
inside_flag = ( (angle/4) & 0x1 ) ;
#endif
return (inside_flag) ;
}
#undef QUADRANT
#undef Y_INTERCEPT
/* ======= Triangle half-plane algorithm ===
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
Graphics Gems 1~5全系列的代码分享 (575个子文件)
00README 1KB
dither.3 4KB
inv_cmap.3 2KB
table.awk 1KB
gemsiv.bib 28KB
bitmap_1 91B
bitmap_2 161B
bitmap_3 2KB
ptinpoly.c 56KB
ZRendv10.c 38KB
collide.c 29KB
graph.C 26KB
construct.c 24KB
p_test.c 24KB
implicit.c 24KB
revfit.c 24KB
algebra3.c 23KB
algebra3.c 23KB
filter_rcg.c 22KB
conmat.c 21KB
bezlen.c 20KB
VecLib4d.c 19KB
quarcube.c 18KB
monotone.c 17KB
NurbSubdiv.c 17KB
vec_h.c 17KB
edgeCalc.c 16KB
Decompose.c 15KB
FitCurves.c 15KB
bsp.c 14KB
inv_cmap.c 14KB
clahe.c 14KB
tga.c 13KB
rad.c 13KB
bounding_volumes.c 13KB
gif.c 12KB
GraphicsGems.c 12KB
partition.c 12KB
NearestPoint.c 12KB
FastMatMul.c 12KB
filter.c 12KB
quantizer.c 12KB
triangleCube.c 12KB
bspPartition.c 11KB
convolve.c 11KB
encodgif.c 11KB
GGVecLib.c 11KB
VecLib.c 11KB
GraphicsGems.c 11KB
contour.c 10KB
hot.c 10KB
Polyintr.c 10KB
c_format.c 10KB
x11.c 10KB
GGVecLib.c 10KB
ellipsoid.c 10KB
sqfinal.c 9KB
layout.C 9KB
viewcorr.c 9KB
smooth.c 9KB
sparse.c 9KB
patch_conv.C 9KB
scallops8.c 9KB
con2d.c 8KB
pcube.c 8KB
bspTree.c 8KB
xcoord.c 8KB
dither.c 8KB
mswindow.C 8KB
exthit.C 8KB
room.c 8KB
bzrinter.c 8KB
coons_warp.c 8KB
planeSets.c 7KB
AAPolyScan.c 7KB
accForm.c 7KB
motblur.c 7KB
bitmap.c 7KB
ellihelp.c 7KB
halfadap.c 7KB
hemis.c 7KB
fpcube.c 7KB
quadedge.C 7KB
ran_ramp.c 7KB
cross.c 7KB
Interleave.c 6KB
rat.c 6KB
NurbEval.c 6KB
vectorize.C 6KB
ray_cyl.c 6KB
inv_fast.c 6KB
tri.c 6KB
Polyhedron.c 6KB
color.c 6KB
panorama.c 6KB
AATables.c 6KB
bspCollide.c 6KB
tobw.c 6KB
timing.c 6KB
Scene3D.c 5KB
共 575 条
- 1
- 2
- 3
- 4
- 5
- 6
资源评论
阿狸的爱
- 粉丝: 0
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功