Python和科学计算认证群组  - 讨论区

标题:关于scipy.optimize.fmin,光线追

2012年02月22日 星期三 09:00

最近在做毕业论文,涉及到光线追踪,NURBS曲面等。

我已经把NURBS曲面相关的东西弄好了。现在做光线追踪。不知道有什么好方法能求直线(光)和NURBS的交点。

我的想法是算出曲线上点和直线的距离,如果距离是0就是直线和NURBS曲线的交点了。

对于2d的NURBS曲线,只有一个参数u,我写了个程序dist(u)来算曲线上对应点到直线的距离,然后 fmin(dist,0.5)来求交点的参数u。

可是一运行就死机。。。

 

不知道坛子里有木有人做过光线追踪方面的东西。有没有比较好的算法来求直线和曲线的交点?(spline或者NURBS都行。)

2012年02月22日 星期三 19:06

把程序贴出来吧。

2012年02月22日 星期三 23:33

# -*- coding: utf-8 -*-

"""

Created on Thu Feb 16 00:50:04 2012

calculate the crosspoint a line with a curve  

 

@author: alaya

"""

 

from pylab import plot,show

from numpy import array,zeros,ones,linalg,sqrt,dot,linspace,shape,\

                  insert,append,cross,abs

 

from scipy.optimize import fmin

 

 

 

 

 

######## The NURBS ralated function ########

 

'''find span'''

def findspan(p,u,U):

       n=len(U)-p-1

       if u==U[n+1]: return (n-1);

       low = int(p) 

       high = int(n+1)

       mid = int((low + high)/2)

       while u<U[mid] or u>=U[mid+1]:

         if u<U[mid]:high = mid

         else: low = mid

         mid = int((low+high)/2)

       return (mid)

 

 

 

'''basis function'''

 

def basis(u,p,U):                 

        '''geben die nicht nur basis funktion als ein Reihe von N[0]=1 bis N[p]''' 

        i = findspan (p,u,U)

 

 

        N = array(ones(p+1))

        left = array(zeros(p+1))

        right = array(zeros(p+1))

        for  j in xrange(1,p+1):

 

           left [j] = u-U[i+1-j]

           right[j] = U[i+j]-u

           saved = 0

           for r in xrange (j):

              temp = N[r]/(right[r+1]+left[j-r])

              N[r] = saved + right[r+1]*temp

              saved = left[j-r]*temp

           N[j]= saved

 

        return (N)

 

 

def d_basis(u,p,U,k=1):  #calc devariation basisfunction first order,p72,eq 2.7

        i = findspan (p,u,U)

 

 

        N = ones([p+1,p+1])   #basisfunction

        Nd = zeros([k+1,p+1])  # derivated basisfunction, k derivation order

 

 

        left = zeros(p+1)

        right = zeros(p+1)

 

        for  j in xrange(1,p+1):

 

           left [j] = u-U[i+1-j]

           right[j] = U[i+j]-u

           saved = 0.0

           for r in xrange (j):

              N[j][r] = right[r+1]+left[j-r]

              temp = N[r][j-1]/N[j][r]

 

              N[r][j] = saved + right[r+1]*temp

              saved = left[j-r]*temp

           N[j][j]= saved

 

        Nd[0] = N[:,p]

 

        for r in xrange(p+1):

            a = ones([2,p+1]) #coefficient

            s1,s2 = 0,1

 

            for g in xrange(1,k+1):

                d=0.0

                rg = r-g

                pg = p-g

 

 

                if r>=g:

                    a[s2][0] = a[s1][0]/N[pg+1][rg]

                    d= a[s2][0]*N[rg][pg]

 

                if rg>=-1:

                    j1 = 1

                else: j1 = -rg

 

 

                if r-1<=pg:

                    j2 = g-1

                else: j2 = p-r

 

 

                for j in xrange(j1,j2+1):

                    a[s2][j] = a[s1][j]-a[s1][j]-a[s1][j-1]/N[pg+1][rg+j]

                    d += a[s2][j]*N[rg+j][pg]

                if r<=pg:

                    a[s2][g] = -a[s1][g-1]/N[pg+1][r]

                    d += a[s2][g]*N[r][pg]

                Nd[g][r] = d

                s1,s2 = s2,s1

 

        r = p

        for g in xrange(1,k+1):

            for j in xrange(p+1):     

                Nd[g][j]*=r

            r *= p-g

 

        return Nd

 

 

 

def curvepoints(p,U,P,u,W=zeros(1)):  #calculate the point on curve

        '''p: degree:::U: knot vector:::u: knot:::P:  control points:::n: the nummber of points'''

 

        span = findspan(p,u,U)

 

        N = basis(u,p,U)

 

        #print '\nN:',N,'P:',P[span-p:span+1],'\n'

 

        if len(W) != 1:

 

            Pw = P*W

            point = dot(N,Pw[span-p:span+1])

            point = point/dot(N,W[span-p:span+1])

 

        else: 

 

            point = dot(N,P[span-p:span+1])

 

        return (point)     

 

def curvderiv(p,U,P,u,g,W=zeros(3)): #calculate the dx/du on curve

        '''p: degree:::U: knot vector:::u: knot:::P:  control points

           n: the nummber of points:::W weightvector:::g derivation order'''   

        span = findspan(p,u,U)

        Nd = d_basis(u,p,U,g)

        Ndg = Nd[g]

        Nd0 = Nd[0]

        if len(W) != 3:

 

            Pw = P*W

            A =  dot (Nd0,Pw[span-p:span+1])

            derA = dot(Ndg,Pw[span-p:span+1])

            w = dot(Nd0,W[span-p:span+1])

            derw = dot(Ndg,W[span-p:span+1])

 

            der = (w*derA-derw*A)/w**2

 

        else: 

 

            der = dot(Ndg,P[span-p:span+1])

        return der

 

 

 

def add_CP_single(Pw,U,p,u):#P149

    Pw1 = zeros([shape(Pw)[0],shape(Pw)[1]+1])

    i = findspan(p,u,U) 

 

    U1 = insert(U,i+1,u)

    #print i,u,U1,'i,u,U1'   

    Pw1[:,:i-p+1] = Pw[:,:i-p+1]

    Pw1[:,i+1:] = Pw[:,i:]

    #print Pw1,'tempered Pw'

    for k in range(i-p+1,i+1):

 

        temp = (u-U[k])/(U[k+p]-U[k])

        #print k,temp

        Pw1[:,k] = temp * Pw[:,k] + (1-temp) * Pw[:,k-1]

 

    return U1,Pw1    

 

 

 

def NURBS_deg_plus(U,p): #

 

    U1 = array([])

    for i in range(len(U)-1):

 

        U1 = append(U1,U[i])

        if U[i] < U[i+1]:

            U1 = append(U1,U[i])

 

    U1 = append(U1,U[-2:])        

 

 

 

 

    return U1

 

def BEZIER_deg_plus(CPw):

    l = len(CPw[0])

    CPw1 = append(CPw,[[0],[0],[0]],axis = 1)

    for i in range(1,l):

        CPw1[:,i] = (1-float(i)/l)*CPw[:,i] + float(i)/l*CPw[:,i-1]    

    #print CPw1,'zwichen Punkt\n'

    CPw1[:,0] = CPw[:,0]

    CPw1[:,-1] = CPw[:,-1]

 

    return CPw1

 

######## END The NURBS ralated function ########

##### BEGIN The Raytrace ralated function ######

 

def dist(P0,V,P): #P0,V defined a line in 2d, P is the other point

    Vn = V/sqrt(sum(V**2))  #the distance a point to a line

    d = cross(P-P0,Vn)

    return abs(d)

 

 

'''    

def distNURBS(u):#calc the distance between a points on NURBS @ u and the line

    Px = curvepoints(p,U,CP[0],u,W)

    Py = curvepoints(p,U,CP[1],u,W)

    PN = array([Px,Py]) #points of NURBS

    d = dist(P0,V,PN)

    #d = cross(PN-P0,V)

    print d

    return abs(d)

'''        

 

def refractThrough(V,normal,n):

        Vn = V/linalg.norm(V)

        normal = normal/linalg.norm(normal)

        cosa = dot(Vn,normal)

        sina = sqrt(1-cosa**2)

        sinb = sina/n

        cosb = sqrt(1-sinb**2)

        temp = n*cosb-cosa

        Vn1 = Vn+temp*normal

        return Vn1

 

 

 

 

###### END The Raytrace ralated function #######

 

 

 

test_P0 = array([-1.0,0])

 

test_V = array([1,0.1])

test_P1 = test_P0 + 10*test_V

plot([-1,9],[0,1])

test_CP = array([[0.0,1.0,1.8,2.4,2.8,3.0],[0.0,1.0,2.0,3.0,4.0,5.0]])

plot(test_CP[0],test_CP[1])

test_U = array([0,0,0,0,0.3333,0.6667,1,1,1,1])

#Pcross,Dcross = CrossNURBS(3,test_U,test_CP,test_P0,test_V)

Px = curvepoints(3,test_U,test_CP[0],0)

Py = curvepoints(3,test_U,test_CP[1],0)

PN = array([Px,Py])

print dist(test_P0,test_V,PN),'distance u=0'

 

 

def find_u(u):

    u = u-int(u)

    tempx = curvepoints(3,test_U,test_CP[0],u)

    tempy = curvepoints(3,test_U,test_CP[1],u)

    tempP = array([tempx,tempy])

    tempd = dist(test_P0,test_V,tempP)

    return tempd**2

 

u = fmin(find_u,0.5)

print u

2012年02月22日 星期三 23:34

中间好大一段是关于NURBS曲线计算的。

我自己也在别的程序中用了fmin,都没问题。。不知道怎么这个程序一运行就死机。

2012年02月23日 星期四 10:19

稍微调试了一下,你可以试试运行find_u(-0.5),这将使得findspan()中那个while循环无法退出。此时findspan()的参数为:

p=3,

u=-0.5

U =[ 0.      0.      0.      0.      0.3333  0.6667  1.      1.      1.    1.    ]

如果find_u的参数不可能为负数的话,你可以:

 

def find_u(u):

    if u < 0: return 100000

    ......

2012年02月23日 星期四 15:10

 谢谢楼上!还费力看代码。。

 

还想请问下,楼上是怎么调试的?

比如这中无限循环的情况系统也不会报错。。也不会告诉你哪里出问题了。。

2012年02月23日 星期四 15:13

另外有什么办法实现这种带边界限制的优化?

2012年02月23日 星期四 15:24

调试方法很简单,在find_u最前面添加一行print u,那么最后那个显示的u值就是进入无限循环的那个u值。接下来试着运行find_u(u),程序进入死循环,按ctrl+c,可以看到强制退出程序时位置,那个就是死循环的位置。边界限制就通过在find_u中添加判断边界,如果出界则返回一个很大的数即可。

2012年02月23日 星期四 15:31

哦~~!

另外怎么才能调用fmin的时候不输出优化过程的信息比如

Optimization terminated successfully.

         Current function value: 0.000000

         Iterations: 12

         Function evaluations: 24

 

 

2012年02月24日 星期五 21:33

问题已经解决了。。再次感谢。

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2020

    京ICP备05028076号