Matlab中inpoly函数的fortran版本,支持向量(绝对原创,欢迎验证)

程序源码(发现问题及时联系yueliang2100@163.com谢谢)

module inpolygon
implicit none

contains
function 
inpoly(p,node,edge_,TOL_) result(in_on)

!  INPOLY: Point-in-polygon testing.
!
! Determine whether a series of points lie within the bounds of a polygon
! in the 2D plane. General non-convex, multiply-connected polygonal
! regions can be handled.
!
! SHORT SYNTAX:
!
!   in_on = inpoly(p,node);
!
!   p   : The points to be tested as an Nx2 array [x1 y1; x2 y2; etc].
!   node: The vertices of the polygon as an Mx2 array [X1 Y1; X2 Y2; etc].
!         The standard syntax assumes that the vertices are specified in
!         consecutive order.
!
!   in_on : An Nx1 logical array with IN_ON(:,1) = in, IN_ON(:,2) = on
!   in  : An Nx1 logical array with IN(i) = TRUE if P(i,:) lies within the
!         region.
!   on  : An Nx1 logical array with ON(i) = TRUE if P(i,:) lies on a
!        polygon edge. (A tolerance is used to deal with numerical
!        precision, so that points within a distance of
!        eps^0.8*norm(node(:),inf) from a polygon edge are considered "on"
!        the edge.
!
! LONG SYNTAX:
!
!  in_on = inpoly(p,node,edge);
!
!  edge: An Mx2 array of polygon edges, specified as connections between
!        the vertices in NODE: [n1 n2; n3 n4; etc]. The vertices in NODE
!        do not need to be specified in connsecutive order when using the
!        extended syntax.
!
! EXAMPLE:
!
!   PIPTest:       ! Will run a few examples
!
! The algorithm is based on the crossing number test, which counts the
! number of times a line that extends from each point past the right-most
! region of the polygon intersects with a polygon edge. Points with odd
! counts are inside. A simple implementation of this method requires each
! wall intersection be checked for each point, resulting in an O(N*M)
! operation count.
!
!   YUE HongLiang  : 2009-2010
!   Email          : yuehongliang0910@gmail.com
!   Last updated   : 11/02/2010 with CVF 6.6
!
! Problems or suggestions? Email me.

real,dimension(:,:),intent(in) :: p,node
integer,dimension(:,:),intent(in),optional :: edge_
real,intent(in),optional :: TOL_
logical,dimension(size(p,1),2) :: in_on
!--------------------------------------------------------------------------
logical,dimension(size(p,1)) :: in,on
integer::i,nnode,n,nc,n1,n2
real ::x1,x2,y1,y2,xmin,xmax,TOL,X(size(p,1)),Y(size(p,1)),delt(size(p,1))
integer,dimension(:,:),allocatable :: edge
!! ERROR CHECKING
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

if present(TOL_) ) then
    
TOL = TOL_
else
    
TOL = 1.0e-12
end if
nnode = size(node,1)
if size(p,2)/=2 ) then
   write
(*,'(A)''P must be an Nx2 array.'
   
return
end if
if 
size(node,2)/=2 ) then
   write
(*,'(A)''NODE must be an Mx2 array.'
   
return
end if

if 
(present(edge_) ) then 
    allocate
(edge(size(edge_,1),2))
    edge =edge_
    
if size(edge,2)/=2 ) then
       write
(*,'(A)''EDGE must be an Mx2 array.'
       
return
    end if
    if 
( (maxval(edge)>nnode).Or.(any(edge<1)) ) then
       write
(*,'(A)''Invalid EDGE.' 
       
return
    end if
else 
! Build edge if not passed
    
allocate(edge(nnode,2))
    edge = 
reshape( (/(i,i=1,nnode),(i,i=2,nnode),1/), (/nnode,2/) )
end if 

!! PRE-PROCESSING
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

in .false.         ! Because we're dealing with mod(in,2) we don't have
                     ! to actually increment the crossing number, we can
                     ! just flip a logical at each intersection (faster!)

on = in
n  = size(p,1)
nc = 
size(edge,1)
! Choose the direction with the biggest range as the "y-coordinate" for the
! test. This should ensure that the sorting is done along the best
! direction for long and skinny problems wrt either the x or y axes.

X = p(:,1)
Y = p(:,2)
TOL = TOL*
minvalmaxval(p,dim=1) - minval(p,dim=1) )
!! MAIN LOOP
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Loop through edges

do i=1,nc 
    
! Nodes in current edge
    
n1 = edge(i,1)
    n2 = edge(i,2)

    
! Endpoints - sorted so that [x1,y1] & [x2,y2] has y1<=y2
    !           - also get xmin = min(x1,x2), xmax = max(x1,x2)
    
y1 = node(n1,2)
    y2 = node(n2,2)
    
if (y1<y2) then
        
x1 = node(n1,1)
        x2 = node(n2,1)
    
else
        
y1 = node(n2,2) ! y1 <=> y2
        
y2 = node(n1,2)
        x1 = node(n2,1)
        x2 = node(n1,1);
    
end if
    if 
(x1>x2) then
        
xmin = x2
        xmax = x1
    
else
        
xmin = x1
        xmax = x2
    
end if
    
delt = abs( (Y-y1)*(X-x2)-(Y-y2)*(X-x1) )
    
where( (Y>y1).and.(Y<=y2).and.((y2-y1)*(X-x1)<(Y-y1)*(x2-x1)) )             ! in the polygon 
!     where( (Y>=y1).and.(Y<y2).and.((y2-y1)*(X-x1)<(Y-y1)*(x2-x1)) ) 
        
in .not.in        
    elsewhere
( (Y>=y1).and.(Y<=y2).and.(X>=xmin).and.(X<=xmax).and.(delt<TOL) ) ! on the edge
        
on = on .or. .true. 
    
end where
!     where( on.and.in ) in = .not.in
    
in = (.not.(on.and.in).and.in)
end do
in_on(:,1) = in .or. on
in_on(:,2) = on

end function inpoly

end module inpolygon

测试代码

program PIPTest
use inpolygon
! real::node(3,2)=(/1.0,1.0,0.0,&
!                   0.0,1.0,1.0/),&
!       p(3,2)=(/1.0,0.6,2.0,&
!                0.5,0.6,1.0/)
! integer::edge(3,2)=(/1,2,3,&
!                      2,3,1/)

real::node(8,2)=(/1.0,0.0,-1.0, 0.0,2.0,0.0,-2.0, 0.0,&
                  
0.0,1.0, 0.0,-1.0,0.0,2.0, 0.0,-2.0/),&
     
p(16,2)=(/0.5,-0.5,-1.5,-0.5,1.5,-1.0,-3.0,-1.0,0.8,-0.8,-0.8, 0.8,0.4,-0.4,-0.4, 0.4,&
               
0.0, 1.0, 0.0,-1.0,0.0, 2.0, 0.0,-2.0,0.8, 0.8,-0.8,-0.8,0.4, 0.4,-0.4,-0.4/)
integer::edge(8,2)=(/1,2,3,4,5,6,7,8,&
                     
2,3,4,1,6,7,8,5/)
logical,dimension(16,2) :: inon
inon = inpoly(p,node,edge)

write(*,'(A5,16L)''in=',inon(:,1)
end program PIPTest

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yueliang2100

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值