Advertisement
jaapverheggen

raytrace5

May 26th, 2015
548
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 29.61 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Sun Apr 12 20:59:12 2015
  4.  
  5. Preliminary code for ray tracing with python
  6. prereq: vtk.
  7. Thanks to https://pyscience.wordpress.com/2014/10/05/from-ray-casting-to-ray-tracing-with-python-and-vtk/
  8.  
  9. In order to proceed, you will have to exit the renderwindow, it is waiting for your input.
  10.  
  11. @author: jaap
  12. """
  13.  
  14. import vtk
  15. import numpy as np
  16. import matplotlib.pyplot as plt
  17.  
  18.  
  19. RayCastLength = 100
  20. ColorRay = [1.0, 1.0, 0.0]
  21. ColorRayMiss = [1.0, 1.0, 1.0]
  22.  
  23. l2n = lambda l: np.array(l)
  24. n2l = lambda n: list(n)
  25.  
  26. def addPoint(ren, appendFilter, p, color=[0.0, 0.0, 0.0], radius=0.2, ):
  27.     point = vtk.vtkSphereSource()
  28.     point.SetCenter(p)
  29.     point.SetRadius(radius)
  30.     point.SetPhiResolution(100)
  31.     point.SetThetaResolution(100)
  32.     # map point
  33.     mapper = vtk.vtkPolyDataMapper()
  34.     mapper.SetInputConnection(point.GetOutputPort())
  35.     # set actor for point
  36.     actor = vtk.vtkActor()
  37.     actor.SetMapper(mapper)
  38.     actor.GetProperty().SetColor(color)
  39.     #draw point in renderer
  40.     ren.AddActor(actor)
  41.     #appendFilter.AddInput(line.GetOutput())
  42.     #appendFilter.Update()
  43.  
  44. def addLine(ren, appendFilter, p1, p2, color=[0.0, 0.0, 1.0], opacity=1.0):
  45.     line = vtk.vtkLineSource()
  46.     line.SetPoint1(p1)
  47.     line.SetPoint2(p2)
  48.  
  49.     mapper = vtk.vtkPolyDataMapper()
  50.     mapper.SetInputConnection(line.GetOutputPort())
  51.  
  52.     actor = vtk.vtkActor()
  53.     actor.SetMapper(mapper)
  54.     actor.GetProperty().SetColor(color)
  55.     actor.GetProperty().SetOpacity(opacity)
  56.     actor.GetProperty()
  57.  
  58.     ren.AddActor(actor)
  59.    
  60.     appendFilter.AddInput(line.GetOutput())
  61.     appendFilter.Update()
  62.  
  63.  
  64. def isHit(obbTree, pSource, pTarget):
  65.     """Returns True if the line intersects with the mesh in 'obbTree'"""
  66.     code = obbTree.IntersectWithLine(pSource, pTarget, None, None)
  67.     if code == 0:
  68.         return False
  69.     return True
  70.  
  71. def GetIntersect(obbTree, pSource, pTarget):
  72.     # Create an empty 'vtkPoints' object to store the intersection point coordinates
  73.     points = vtk.vtkPoints()
  74.     # Create an empty 'vtkIdList' object to store the ids of the cells that intersect
  75.     # with the cast rays
  76.     cellIds = vtk.vtkIdList()
  77.    
  78.     # Perform intersection
  79.     code = obbTree.IntersectWithLine(pSource, pTarget, points, cellIds)
  80.     assert (code != 0)
  81.     # Get point-data
  82.     pointData = points.GetData()
  83.     # Get number of intersection points found
  84.     noPoints = pointData.GetNumberOfTuples()
  85.     # Get number of intersected cell ids
  86.     noIds = cellIds.GetNumberOfIds()
  87.    
  88.     assert (noPoints == noIds)
  89.     assert (noPoints > 0)
  90.     # Loop through the found points and cells and store
  91.     # them in lists
  92.     pointsInter = []
  93.     cellIdsInter = []
  94.     for idx in range(noPoints):
  95.         pointsInter.append(pointData.GetTuple3(idx))
  96.         cellIdsInter.append(cellIds.GetId(idx))
  97.    
  98.     return pointsInter, cellIdsInter
  99.  
  100. def calcVecReflect(vecInc, vecNor):
  101.     '''    
  102.    http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf
  103.    Vector reflect(const Vector& normal, const Vactor& incident)
  104.    {
  105.        const double cosI = -dot(normal, incident);
  106.        return incident + 2 * cosI * normal;
  107.    }  
  108.    '''
  109.     vecInc = l2n(vecInc)
  110.     vecNor = l2n(vecNor)
  111.     cosI = -np.dot(vecNor, vecInc)
  112.     vecRef = vecInc + 2*cosI*vecNor
  113.     return n2l(vecRef)
  114.  
  115.  
  116. def calcVecRefract(vecInc, vecNor, n1=1.0, n2=1.33):
  117.     '''
  118.    http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf
  119.    Vector refract(Const Vector& normal, const Vector& incident, double n1, double n2)
  120.    {
  121.         const double n = n1/n2;
  122.         const double cosI = -dot(normal, incident)
  123.         const double sinT2 = n*n*(1.0-cosI*cosI);
  124.         if (sinT2 > 1.0) return Vactor::invalid; //TIR
  125.         const double cosT = sqrt(1.0 - sinT2);
  126.         return n * incident + (n * cosI - cosT) * normal;
  127.    }
  128.    n1 = first medium, n2 is second medium
  129.    '''
  130.     n=n1/n2
  131.     vecInc = l2n(vecInc)
  132.     vecNor = l2n(vecNor)    
  133.     cosI = -np.dot(vecNor, vecInc)
  134.     sinT2 = n**2*(1-cosI**2)
  135.     assert (sinT2 < 1.0)
  136.     if sinT2 < 1.0:
  137.         cosT = np.sqrt(1.0-sinT2)
  138.         vecRef = n * vecInc + (n * cosI - cosT) * vecNor
  139.         return n2l(vecRef)
  140.     else:
  141.         return 'blah'
  142.  
  143. def vtkspheresource(ren, appendFilter, srf ):
  144.     # Create and configure sphere, radius is focalpoint
  145.     location = [0.0,0.0,0.0] #It's the source, so location is zero    
  146.     startendtheta = 180*np.arcsin(0.5*srf['diam']/srf['fp'])/np.pi  
  147.     print startendtheta
  148.     sphere = vtk.vtkSphereSource()
  149.     sphere.SetCenter(location)
  150.     sphere.SetRadius(srf['fp'])
  151.     sphere.SetThetaResolution(srf['resolution']*3)
  152.     sphere.SetPhiResolution(srf['resolution'])
  153.     #sphere.SetStartTheta(90-startendtheta)  # create partial sphere
  154.     #sphere.SetEndTheta(90+startendtheta)    
  155.     sphere.SetStartPhi(180-startendtheta)  # create partial sphere
  156.     sphere.SetEndPhi(180)  
  157.     # rotate and move such that the source goes through 0,0,0 and is oriented along the z axis
  158.     transform = vtk.vtkTransform()
  159.     transform.RotateWXYZ(180,1,0,0)
  160.     transform.Translate(0.0,0.0,srf['fp'])
  161.     transformFilter=vtk.vtkTransformPolyDataFilter()
  162.     transformFilter.SetTransform(transform)
  163.     transformFilter.SetInputConnection(sphere.GetOutputPort())
  164.     transformFilter.Update()
  165.     # Create mapper and set the mapped texture as input
  166.     mapperSphere = vtk.vtkPolyDataMapper()
  167.     mapperSphere.SetInput(transformFilter.GetOutput())
  168.     # Create actor and set the mapper and the texture
  169.     actorSphere = vtk.vtkActor()
  170.     actorSphere.SetMapper(mapperSphere)
  171.     actorSphere.GetProperty().SetColor([1.0, 0.0, 0.0])  #set color to yellow
  172.     actorSphere.GetProperty().EdgeVisibilityOn()  # show edges/wireframe
  173.     actorSphere.GetProperty().SetEdgeColor([0.0, 0.0, 0.0])  #render edges as white
  174.     #Create points
  175.     cellCenterCalcSource = vtk.vtkCellCenters()
  176.     cellCenterCalcSource.SetInput(transformFilter.GetOutput())
  177.     cellCenterCalcSource.Update()
  178.     # Get the point centers from 'cellCenterCalc'
  179.     pointsCellCentersSource = cellCenterCalcSource.GetOutput(0)
  180.     # dummy point container
  181.     normal_points = vtk.vtkPoints()
  182.     # Loop through all point centers and add a point-actor through 'addPoint'
  183.     for idx in range(pointsCellCentersSource.GetNumberOfPoints()):
  184.         addPoint(ren, False, pointsCellCentersSource.GetPoint(idx), [1.0, 1.0, 0.0])
  185.         normal_points.InsertNextPoint(pointsCellCentersSource.GetPoint(idx))
  186.    
  187.     # Create a new 'vtkPolyDataNormals' and connect to the 'Source' half-sphere
  188.     normalsCalcSource = vtk.vtkPolyDataNormals()
  189.     normalsCalcSource.SetInputConnection(transformFilter.GetOutputPort())
  190.     # Disable normal calculation at cell vertices
  191.     normalsCalcSource.ComputePointNormalsOff()
  192.     # Enable normal calculation at cell centers
  193.     normalsCalcSource.ComputeCellNormalsOn()
  194.     # Disable splitting of sharp edges
  195.     normalsCalcSource.SplittingOff()
  196.     # Disable global flipping of normal orientation
  197.     normalsCalcSource.FlipNormalsOff()
  198.     # Enable automatic determination of correct normal orientation
  199.     normalsCalcSource.AutoOrientNormalsOn()
  200.     # Perform calculation
  201.     normalsCalcSource.Update()
  202.     '''# Test glyphs,   turned off for now
  203.    glyphsa = glyphnormals(refract_polydata)
  204.    ren.AddActor(glyphsa)'''
  205.     # Plot and save
  206.     ren.AddActor(actorSphere)
  207.     appendFilter.AddInput(transformFilter.GetOutput())
  208.     appendFilter.Update()
  209.     # set camera properties
  210.     camera = ren.MakeCamera()
  211.     camera.SetPosition(-100, 100, 100)
  212.     camera.SetFocalPoint(0.0, 0.0, 0.0)
  213.     camera.SetViewAngle(30.0)
  214.     ren.SetActiveCamera(camera)
  215.     return transformFilter, normal_points, normalsCalcSource
  216.  
  217. def glyphnormals(ren, normals):
  218.     # this doesn't work, it will always go to the normal,
  219.     dummy_cellCenterCalcSource = vtk.vtkCellCenters()
  220.     dummy_cellCenterCalcSource.VertexCellsOn()
  221.     dummy_cellCenterCalcSource.SetInputConnection(normals.GetOutputPort())
  222.     # Create a new 'default' arrow to use as a glyph
  223.     arrow = vtk.vtkArrowSource()
  224.     # Create a new 'vtkGlyph3D'
  225.     glyphSource = vtk.vtkGlyph3D()
  226.     # Set its 'input' as the cell-center normals calculated at the Source's cells
  227.     glyphSource.SetInputConnection(dummy_cellCenterCalcSource.GetOutputPort())
  228.     # Set its 'source', i.e., the glyph object, as the 'arrow'
  229.     glyphSource.SetSourceConnection(arrow.GetOutputPort())
  230.     # Enforce usage of normals for orientation
  231.     glyphSource.SetVectorModeToUseNormal()
  232.     # Set scale for the arrow object
  233.     glyphSource.SetScaleFactor(1)
  234.     # Create a mapper for all the arrow-glyphs
  235.     glyphMapperSource = vtk.vtkPolyDataMapper()
  236.     glyphMapperSource.SetInputConnection(glyphSource.GetOutputPort())
  237.     # Create an actor for the arrow-glyphs
  238.     glyphActorSource = vtk.vtkActor()
  239.     glyphActorSource.SetMapper(glyphMapperSource)
  240.     glyphActorSource.GetProperty().SetColor([1.0,1.0,0.0])
  241.     # Add actor
  242.     ren.AddActor(glyphActorSource)
  243.  
  244. def glyphs(cells):
  245.     # Visualize normals as done previously but using refracted or reflected cells
  246.     arrow = vtk.vtkArrowSource()
  247.     glyphCell = vtk.vtkGlyph3D()
  248.     glyphCell.SetInput(cells)
  249.     glyphCell.SetSourceConnection(arrow.GetOutputPort())
  250.     glyphCell.SetVectorModeToUseNormal()
  251.     glyphCell.SetScaleFactor(1)
  252.    
  253.     glyphMapperCell = vtk.vtkPolyDataMapper()
  254.     glyphMapperCell.SetInputConnection(glyphCell.GetOutputPort())
  255.    
  256.     glyphActorCell = vtk.vtkActor()
  257.     glyphActorCell.SetMapper(glyphMapperCell)
  258.     glyphActorCell.GetProperty().SetColor([1.0,1.0,1.0])
  259.     return glyphActorCell
  260.  
  261.  
  262. def vtklenssurface(ren, appendFilter, srf):
  263.     phi = 180*np.arcsin(0.5*srf['diam']/srf['fp'])/np.pi
  264.     lensA = vtk.vtkSphereSource()
  265.     lensA.SetCenter(0.0, 0.0, 0.0) #we will move it later
  266.     lensA.SetThetaResolution(100)
  267.     lensA.SetPhiResolution(20)
  268.     lensA.SetRadius(srf['fp'])
  269.     lensA.SetStartPhi(180-phi)  # create partial sphere
  270.     lensA.SetEndPhi(180)
  271.     #Transform
  272.     transform = vtk.vtkTransform()
  273.     if srf['curv'] == 'positive':
  274.         location = srf['location'][:]
  275.         location[2] = srf['location'][2]+srf['fp'] #if I want the location exactly, h=R-np.sqrt(R**2-(w/2)**2)
  276.         transform.Translate(location)        
  277.         print location
  278.         print srf['location']
  279.     elif srf['curv'] == 'negative':
  280.         #Transform
  281.         transform.RotateWXYZ(180,1,0,0)
  282.         lensBt=vtk.vtkTransformPolyDataFilter()
  283.         lensBt.SetTransform(transform)
  284.         lensBt.SetInputConnection(lensA.GetOutputPort())
  285.         lensBt.Update()
  286.         location = srf['location'][:]
  287.         location[2] = srf['location'][2]-srf['fp'] #if I want the location exactly, h=R-np.sqrt(R**2-(w/2)**2)
  288.         lensA = lensBt
  289.         transform = vtk.vtkTransform() #redfine transform
  290.         transform.Translate(location)
  291.         print location
  292.         print srf['location']
  293.     else:
  294.         print "not negative or positive"
  295.    
  296.     lensAt=vtk.vtkTransformPolyDataFilter()
  297.     lensAt.SetTransform(transform)
  298.     lensAt.SetInputConnection(lensA.GetOutputPort())
  299.     lensAt.Update()
  300.     # Map
  301.     lensAm = vtk.vtkPolyDataMapper()
  302.     lensAm.SetInput(lensAt.GetOutput())
  303.     # Create actor
  304.     lensAa = vtk.vtkActor()
  305.     lensAa.SetMapper(lensAm)
  306.     lensAa.GetProperty().SetColor([0.0,0.0,1.0])  #set color to yellow
  307.     lensAa.GetProperty().EdgeVisibilityOn()  # show edges/wireframe
  308.     lensAa.GetProperty().SetEdgeColor([1.0,1.0,1.0])  #render edges as white
  309.     # Plot and save
  310.     ren.AddActor(lensAa)
  311.     appendFilter.AddInput(lensAt.GetOutput())
  312.     appendFilter.Update()
  313.     # set camera properties
  314.     camera = ren.MakeCamera()
  315.     camera.SetPosition(-100, 100, 100)
  316.     camera.SetFocalPoint(location)
  317.     camera.SetViewAngle(30.0)
  318.     ren.SetActiveCamera(camera)
  319.     return lensAt
  320.  
  321. def vtkscreen(ren, appendFilter, screen):
  322.     # Create a pentagon
  323.     flat = vtk.vtkRegularPolygonSource()
  324.     #polygonSource.GeneratePolygonOff()
  325.     flat.SetNumberOfSides(4)
  326.     flat.SetRadius(screen['width'])
  327.     flat.SetCenter(screen['center'])
  328.     flat.Update()
  329.      # Create mapper and set the mapped texture as input
  330.     flatm = vtk.vtkPolyDataMapper()
  331.     flatm.SetInputConnection(flat.GetOutputPort())
  332.     flata = vtk.vtkActor()
  333.     # Create actor and set the mapper and the texture
  334.     flata.SetMapper(flatm)
  335.     flata.GetProperty().SetColor([0.3,0.3,0.3])  #set color to grey
  336.     flata.GetProperty().EdgeVisibilityOn()  # show edges/wireframe
  337.     flata.GetProperty().SetEdgeColor([1.0,1.0,1.0])  #render edges as white
  338.     # Plot and save
  339.     ren.AddActor(flata)
  340.     appendFilter.AddInput(flat.GetOutput())
  341.     appendFilter.Update()
  342.     # set camera properties
  343.     camera = ren.MakeCamera()
  344.     camera.SetPosition(-100, 100, 100)
  345.     camera.SetFocalPoint(screen['center'])
  346.     camera.SetViewAngle(30.0)
  347.     ren.SetActiveCamera(camera)
  348.     return flat
  349.  
  350. # get info for rays, they go through the mesh nodes.
  351. def refract(ren, appendFilter, surface1, surface2):
  352.     surf2 = surface2['surface']
  353.     #normalsSource = normalsCalcSource.GetOutput().GetCellData().GetNormals()
  354.     pointsCellCentersSurf1 = surface1['normalpoints']
  355.     if 'refractcells' in surface1:  #technically it is a bit weird that you have to specify which vectors are the right ones,
  356.         normalsCalcSurf1 = surface1['refractcells']
  357.         # vectors of refracted rays        
  358.         normalsSurf1 = normalsCalcSurf1.GetPointData().GetNormals()
  359.     elif 'refractcells' not in surface1 and 'normalcells' in surface1:
  360.         normalsCalcSurf1 = surface1['normalcells']
  361.         # vectors of normal rays
  362.         normalsSurf1 = normalsCalcSurf1.GetOutput().GetCellData().GetNormals()
  363.     else:
  364.         print "problem in surface 1 input parameters function refract"        
  365.     # If 'points' and 'source' are known, then use these.
  366.     # They have to be known, otherwise the wrong order is used. So skip
  367.     # prepare for raytracing
  368.     obbsurf2 = vtk.vtkOBBTree()
  369.     obbsurf2.SetDataSet(surf2.GetOutput())
  370.     obbsurf2.BuildLocator()
  371.    
  372.     # Create a new 'vtkPolyDataNormals' and connect to the target surface
  373.     normalsCalcSurf2 = vtk.vtkPolyDataNormals()
  374.     normalsCalcSurf2.SetInputConnection(surf2.GetOutputPort())
  375.     # Disable normal calculation at cell vertices
  376.     normalsCalcSurf2.ComputePointNormalsOff()
  377.     # Enable normal calculation at cell centers
  378.     normalsCalcSurf2.ComputeCellNormalsOn()
  379.     # Disable splitting of sharp edges
  380.     normalsCalcSurf2.SplittingOff()
  381.     # Disable global flipping of normal orientation for negative curvature
  382.     if 'curv' in surface2:    
  383.         if surface2['curv'] is 'positive':
  384.             normalsCalcSurf2.FlipNormalsOff()
  385.         elif surface2['curv'] is 'negative':
  386.             normalsCalcSurf2.FlipNormalsOn()        
  387.         else:
  388.             print "Problem in surface 2 input parameter curve, function refract"
  389.     # Enable automatic determination of correct normal orientation
  390.     normalsCalcSurf2.AutoOrientNormalsOn()
  391.     # Perform calculation
  392.     normalsCalcSurf2.Update()
  393.     # Extract the normal-vector data at the target surface
  394.     normalsSurf2 = normalsCalcSurf2.GetOutput().GetCellData().GetNormals()
  395.    
  396.     # where intersections are found
  397.     intersection_points = vtk.vtkPoints()
  398.     # vectors where intersections are found
  399.     normal_vectors = vtk.vtkDoubleArray()
  400.     normal_vectors.SetNumberOfComponents(3)
  401.     # normals of refracted vectors
  402.     refract_vectors = vtk.vtkDoubleArray()
  403.     refract_vectors.SetNumberOfComponents(3)
  404.     refract_polydata = vtk.vtkPolyData()
  405.    
  406.     # Loop through all of Source's cell-centers
  407.     for idx in range(pointsCellCentersSurf1.GetNumberOfPoints()):
  408.         # Get coordinates of Source's cell center
  409.         pointSurf1 = pointsCellCentersSurf1.GetPoint(idx)
  410.         # Get normal vector at that cell
  411.         normalsurf1 = normalsSurf1.GetTuple(idx)
  412.         # Calculate the 'target' of the ray based on 'RayCastLength'
  413.         pointRaySurf2 = n2l(l2n(pointSurf1) + RayCastLength*l2n(normalsurf1))
  414.         # Check if there are any intersections for the given ray
  415.         if isHit(obbsurf2, pointSurf1, pointRaySurf2):
  416.             # Retrieve coordinates of intersection points and intersected cell ids
  417.             pointsInter, cellIdsInter = GetIntersect(obbsurf2, pointSurf1, pointRaySurf2)
  418.             # Render lines/rays emanating from the Source. Rays that intersect are
  419.             addLine(ren, appendFilter, pointSurf1, pointsInter[0], ColorRay, opacity=0.25)
  420.             # Render intersection points
  421.             addPoint(ren, False, pointsInter[0], ColorRay)
  422.             # Get the normal vector at the surf2 cell that intersected with the ray
  423.             normalsurf2 = normalsSurf2.GetTuple(cellIdsInter[0])
  424.             # Insert the coordinates of the intersection point in the dummy container
  425.             intersection_points.InsertNextPoint(pointsInter[0])
  426.             # Insert the normal vector of the intersection cell in the dummy container
  427.             normal_vectors.InsertNextTuple(normalsurf2)
  428.             # Calculate the incident ray vector
  429.             vecInc = n2l(l2n(pointRaySurf2) - l2n(pointSurf1))
  430.             # Calculate the reflected ray vector
  431.             #vecRef = calcVecReflect(vecInc, normallensA)
  432.             vecRef = calcVecRefract(vecInc/np.linalg.norm(vecInc), normalsurf2, surface1['rn'], surface2['rn'])
  433.             refract_vectors.InsertNextTuple(vecRef)
  434.             ## Calculate the 'target' of the reflected ray based on 'RayCastLength'
  435.             #pointRayReflectedTarget = n2l(l2n(pointsInter[0]) + RayCastLength*l2n(vecRef))
  436.             ##pointRayReflectedTarget = n2l(l2n(pointsInter[0]) - RayCastLength*l2n(vecRef))
  437.             ## Render lines/rays bouncing off lensA with a 'ColorRayReflected' color
  438.             #addLine(ren, pointsInter[0], pointRayReflectedTarget, ColorRay)
  439.            
  440.     # export normals at lens surface
  441.     normalsCalcSurface2 = vtk.vtkPolyDataNormals()
  442.     normalsCalcSurface2.SetInputConnection(surf2.GetOutputPort())
  443.     # Disable normal calculation at cell vertices
  444.     normalsCalcSurface2.ComputePointNormalsOff()
  445.     # Enable normal calculation at cell centers
  446.     normalsCalcSurface2.ComputeCellNormalsOn()
  447.     # Disable splitting of sharp edges
  448.     normalsCalcSurface2.SplittingOff()
  449.     # Disable global flipping of normal orientation
  450.     normalsCalcSurface2.FlipNormalsOff()
  451.     # Enable automatic determination of correct normal orientation
  452.     normalsCalcSurface2.AutoOrientNormalsOn()
  453.     # Perform calculation
  454.     normalsCalcSurface2.Update()
  455.     # Create a dummy 'vtkPolyData' to store refracted vecs
  456.     refract_polydata.SetPoints(intersection_points)
  457.     refract_polydata.GetPointData().SetNormals(refract_vectors)
  458.     # Return data for next surface, all has been drawn
  459.     '''# Test glyphs,   turned off for now
  460.    glyphsa = glyphs(refract_polydata)
  461.    ren.AddActor(glyphsa)
  462.    '''
  463.     return intersection_points, normalsCalcSurface2,  refract_polydata
  464.  
  465. # get info for rays, they go through the mesh nodes.
  466. def reflect(ren, appendFilter, surface1, surface2):
  467.     surf2 = surface2['surface']
  468.     pointsCellCentersSurf1 = surface1['normalpoints']
  469.     if 'refractcells' in surface1:  #technically it is a bit weird that you have to specify which vectors are the right ones,
  470.         normalsCalcSurf1 = surface1['refractcells']
  471.         # vectors of refracted rays        
  472.         normalsSurf1 = normalsCalcSurf1.GetPointData().GetNormals()
  473.     elif 'reflectcells' in surface1:
  474.         normalsCalcSurf1 = surface1['reflectcells']
  475.         # vectors of reflected rays        
  476.         normalsSurf1 = normalsCalcSurf1.GetPointData().GetNormals()
  477.     elif 'refractcells' not in surface1 and 'reflectcells' not in surface1 and 'normalcells' in surface1:
  478.         normalsCalcSurf1 = surface1['normalcells']
  479.         # vectors of normal rays
  480.         normalsSurf1 = normalsCalcSurf1.GetOutput().GetCellData().GetNormals()
  481.     else:
  482.         print "problem in surface 1 input parameters function refract"        
  483.     # If 'points' and 'source' are known, then use these.
  484.     # They have to be known, otherwise the wrong order is used. So skip
  485.     # prepare for raytracing
  486.     obbsurf2 = vtk.vtkOBBTree()
  487.     obbsurf2.SetDataSet(surf2.GetOutput())
  488.     obbsurf2.BuildLocator()
  489.  
  490.     # Create a new 'vtkPolyDataNormals' and connect to the target surface
  491.     normalsCalcSurf2 = vtk.vtkPolyDataNormals()
  492.     normalsCalcSurf2.SetInputConnection(surf2.GetOutputPort())
  493.     # Disable normal calculation at cell vertices
  494.     normalsCalcSurf2.ComputePointNormalsOff()
  495.     # Enable normal calculation at cell centers
  496.     normalsCalcSurf2.ComputeCellNormalsOn()
  497.     # Disable splitting of sharp edges
  498.     normalsCalcSurf2.SplittingOff()
  499.     # Disable global flipping of normal orientation for negative curvature
  500.     if 'curv' in surface2:    
  501.         if surface2['curv'] is 'positive':
  502.             normalsCalcSurf2.FlipNormalsOff()
  503.         elif surface2['curv'] is 'negative':
  504.             normalsCalcSurf2.FlipNormalsOn()        
  505.         else:
  506.             print "Problem in surface 2 input parameter curve, function refract"
  507.     # Enable automatic determination of correct normal orientation
  508.     normalsCalcSurf2.AutoOrientNormalsOn()
  509.     # Perform calculation
  510.     normalsCalcSurf2.Update()
  511.     # Extract the normal-vector data at the target surface
  512.     normalsSurf2 = normalsCalcSurf2.GetOutput().GetCellData().GetNormals()
  513.    
  514.     # where intersections are found
  515.     intersection_points = vtk.vtkPoints()
  516.     # vectors where intersections are found
  517.     normal_vectors = vtk.vtkDoubleArray()
  518.     normal_vectors.SetNumberOfComponents(3)
  519.     # normals of refracted vectors
  520.     reflect_vectors = vtk.vtkDoubleArray()
  521.     reflect_vectors.SetNumberOfComponents(3)
  522.     reflect_polydata = vtk.vtkPolyData()
  523.    
  524.     # Loop through all of Source's cell-centers
  525.     for idx in range(pointsCellCentersSurf1.GetNumberOfPoints()):
  526.         # Get coordinates of Source's cell center
  527.         pointSurf1 = pointsCellCentersSurf1.GetPoint(idx)
  528.         # Get normal vector at that cell
  529.         normalsurf1 = normalsSurf1.GetTuple(idx)
  530.         # Calculate the 'target' of the ray based on 'RayCastLength'
  531.         pointRaySurf2 = n2l(l2n(pointSurf1) + RayCastLength*l2n(normalsurf1))
  532.         # Check if there are any intersections for the given ray
  533.         if isHit(obbsurf2, pointSurf1, pointRaySurf2):
  534.             # Retrieve coordinates of intersection points and intersected cell ids
  535.             pointsInter, cellIdsInter = GetIntersect(obbsurf2, pointSurf1, pointRaySurf2)
  536.             # Render lines/rays emanating from the Source. Rays that intersect are
  537.             addLine(ren, appendFilter, pointSurf1, pointsInter[0], ColorRay, opacity=0.25)
  538.             # Render intersection points
  539.             addPoint(ren, False, pointsInter[0], ColorRay)
  540.             # Get the normal vector at the surf2 cell that intersected with the ray
  541.             normalsurf2 = normalsSurf2.GetTuple(cellIdsInter[0])
  542.             # Insert the coordinates of the intersection point in the dummy container
  543.             intersection_points.InsertNextPoint(pointsInter[0])
  544.             # Insert the normal vector of the intersection cell in the dummy container
  545.             normal_vectors.InsertNextTuple(normalsurf2)
  546.             # Calculate the incident ray vector
  547.             vecInc = n2l(l2n(pointRaySurf2) - l2n(pointSurf1))
  548.             # Calculate the reflected ray vector
  549.             vecRef = calcVecReflect(vecInc/np.linalg.norm(vecInc), normalsurf2)
  550.             #vecRef = calcVecRefract(vecInc/np.linalg.norm(vecInc), normalsurf2, surface1['rn'], surface2['rn'])
  551.             reflect_vectors.InsertNextTuple(vecRef)
  552.             ## Calculate the 'target' of the reflected ray based on 'RayCastLength'
  553.             #pointRayReflectedTarget = n2l(l2n(pointsInter[0]) + RayCastLength*l2n(vecRef))
  554.             ##pointRayReflectedTarget = n2l(l2n(pointsInter[0]) - RayCastLength*l2n(vecRef))
  555.             ## Render lines/rays bouncing off lensA with a 'ColorRayReflected' color
  556.             #addLine(ren, pointsInter[0], pointRayReflectedTarget, ColorRay)
  557.            
  558.     # export normals at surface
  559.     normalsCalcSurface2 = vtk.vtkPolyDataNormals()
  560.     normalsCalcSurface2.SetInputConnection(surf2.GetOutputPort())
  561.     # Disable normal calculation at cell vertices
  562.     normalsCalcSurface2.ComputePointNormalsOff()
  563.     # Enable normal calculation at cell centers
  564.     normalsCalcSurface2.ComputeCellNormalsOn()
  565.     # Disable splitting of sharp edges
  566.     normalsCalcSurface2.SplittingOff()
  567.     # Disable global flipping of normal orientation
  568.     normalsCalcSurface2.FlipNormalsOff()
  569.     # Enable automatic determination of correct normal orientation
  570.     normalsCalcSurface2.AutoOrientNormalsOn()
  571.     # Perform calculation
  572.     normalsCalcSurface2.Update()
  573.     # Create a dummy 'vtkPolyData' to store refracted vecs
  574.     reflect_polydata.SetPoints(intersection_points)
  575.     reflect_polydata.GetPointData().SetNormals(reflect_vectors)
  576.     # Return data for next surface, all has been drawn
  577.     '''# Test glyphs,   turned off for now
  578.    glyphsa = glyphs(refract_polydata)
  579.    ren.AddActor(glyphsa)
  580.    '''
  581.     return intersection_points, normalsCalcSurface2,  reflect_polydata
  582.  
  583.  
  584. def run(surfaces, project, Directory, scene, plot=1):
  585.     ### write output to vtp file
  586.     writer = vtk.vtkXMLPolyDataWriter()
  587.     filename = Directory+project+"%04d.vtp" % Scene
  588.     writer.SetFileName(filename)
  589.     appendFilter = vtk.vtkAppendPolyData()
  590.    
  591.     ### Create a render window
  592.     ren = vtk.vtkRenderer()
  593.     renWin = vtk.vtkRenderWindow()
  594.     renWin.AddRenderer(ren)
  595.     renWin.SetSize(600,600)
  596.     iren = vtk.vtkRenderWindowInteractor()
  597.     iren.SetRenderWindow(renWin)
  598.     iren.Initialize()
  599.     rays = dict()
  600.     for srf in surfaces:
  601.         # Fill the scene
  602.         if srf['type'] == 'source':
  603.             #Draw source            
  604.             srf['surface'], srf['normalpoints'], srf['normalcells'] = vtkspheresource(ren, appendFilter,srf)
  605.             #Also draw glyphs to see where lines are going
  606.             glyphnormals(ren, srf['normalcells'])
  607.             renWin.Render()
  608.            
  609.         elif srf['type'] == 'lens' and 'normalcells' in rays:
  610.             # Draw refractive surfaces
  611.             srf['surface'] = vtklenssurface(ren, appendFilter, srf)
  612.             renWin.Render()
  613.             srf['normalpoints'], srf['normalcells'], srf['refractcells'] = refract(ren, appendFilter, rays, srf)
  614.             renWin.Render()
  615.            
  616.         elif srf['type'] == 'screen' and 'normalcells' in rays :
  617.             # Draw screen
  618.             srf['surface'] = vtkscreen(ren, appendFilter, srf)
  619.             renWin.Render()
  620.             srf['normalpoints'], srf['normalcells'], srf['reflectcells'] = reflect(ren, appendFilter, rays, srf)
  621.             renWin.Render()
  622.             # Now plot the screen using matplotlib
  623.             if plot == 1:
  624.                 # Get list from screen reflect cells
  625.                 plotlist = range(srf['normalpoints'].GetNumberOfPoints())
  626.                 for idx in range(srf['normalpoints'].GetNumberOfPoints()):
  627.                     plotlist[idx] = srf['normalpoints'].GetPoint(idx)[0:2]
  628.                
  629.                 plt.plot([cc[0] for cc in plotlist], [cc[1] for cc in plotlist], '.')
  630.         rays = srf.copy()
  631.     point = vtk.vtkSphereSource()
  632.     point.SetRadius(1)
  633.     point.SetCenter(0.0,0.0,30.0)
  634.     pointm = vtk.vtkPolyDataMapper()
  635.     pointm.SetInput(point.GetOutput())
  636.     pointa = vtk.vtkActor()
  637.     pointa.SetMapper(pointm)
  638.     ren.AddActor(pointa)
  639.     renWin.Render()
  640.    
  641.     '''# export scene to image
  642.    w2if = vtk.vtkWindowToImageFilter()
  643.    w2if.SetInput(renWin)
  644.    w2if.Update()        
  645.    writer = vtk.vtkPNGWriter()
  646.    writer.SetFileName(Directory+project+"%04d.png" % Scene)
  647.    writer.SetInput(w2if.GetOutput())
  648.    writer.Write() '''
  649.     ### write output to vtp file
  650.     polydatacontainer = appendFilter
  651.     writer.SetInput(polydatacontainer.GetOutput())
  652.     writer.Write()
  653.     # Check results in viewer, by exit screen, proceed
  654.     iren.Start()
  655.     #del renWin, iren
  656.    
  657. #end def main  
  658. # del iren, renWin
  659. surfaces = [{'type' :'source',
  660.              'fp' :1e3,
  661.              'diam' : 10,
  662.              'resolution': 4,
  663.              'rn': 1.0 },
  664.              {'type' :'lens',
  665.              'fp' :75,
  666.              'diam' : 25,
  667.              'location': [0.0, 0.0, 30],
  668.              'rn': 1.5,
  669.              'curv': 'positive' },    # a positive curvature means the focal point is further from the source than the location
  670.             {'type': 'lens',
  671.              'fp' :75,
  672.              'diam' : 25,
  673.              'location': [0.0, 0.0, 33],
  674.              'rn': 1.0,
  675.              'curv': 'negative'},    # a positive curvature means the focal point is further from the source than the location
  676.             {'type': 'screen',
  677.              'width': 50,
  678.              'height': 50,
  679.              'center': [0.0, 0.0, 130.0],  # Only using z, I can still only deal with center axis optics        
  680.              'normal': [0.0, 0.0, -1.0] }]  # Not using, the screen is normal on the central axis
  681.  
  682. #assert 180*np.arcsin(0.5*source['diam']/source['fp'])/np.pi, "source is not well defined"  
  683.  
  684. project = 'test'
  685. Directory = '/home/jaap/Spyder/optics/'
  686. Scene = 0
  687. run(surfaces, project, Directory, Scene, plot=0)
  688. #del iren, renWin
  689.  
  690. Scene  = 1
  691. surfaces[1]['location'] = [0.0, 2.0, 30]
  692. surfaces[2]['location'] = [0.0, 2.0, 33]
  693. run(surfaces, project, Directory, Scene, plot=0)
  694. #del iren, renWin
  695.  
  696. Scene  = 2
  697. surfaces[1]['location'] = [0.0, 4.0, 30]
  698. surfaces[2]['location'] = [0.0, 4.0, 33]
  699. run(surfaces, project, Directory, Scene, plot=0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement