; $Id: streamline.pro,v 1.10 2004/01/21 15:55:03 scottm Exp $ ; Copyright (c) 1991-2004. Research Systems, Inc. All rights reserved. ; Unauthorized reproduction prohibited. ;+ ; NAME: ; STREAMLINE ; ; PURPOSE: ; ; This routine serves to generate the visualization graphics from a ; path. The output is a polygonal ribbon which is tangent to a vector ; field along its length. The ribbon is generated by placing a line at ; each vertex in the direction specified by each normal value multiplied ; by the anisotropy factor. The input normal array is not normalized ; before use, making it possible to vary the ribbon width as well. ; ; CATEGORY: ; 3D Toolkit ; ; CALLING SEQUENCE: ; STREAMLINE, verts, conn, normals, outverts, outconn ; [, ANISOTROPY = vector][, SIZE = vector][, PROFILE = array] ; ; INPUTS: ; ; Verts: Input array of path vertices ([3,N] array). ; Conn: Input path connectivity array in IDLgrPolyline POLYLINES ; keyword format. There is one set of line segments in this ; array for each streamline. ; Normals: Normal estimate at each input vertex ([3,N] array). ; ; ; OUTPUTS: ; ; Outverts: Output vertices ([3,M] float array). Useful if the ; routine is to be used with Direct Graphics or the user wants to ; manipulate the data directly. ; Outconn: Output polygon connectivity array to match the output vertices. ; ; ; OPTIONAL KEYWORD PARAMETERS: ; ;ANISOTROPY: Set this input keyword to a three element array ; describing the distance between grid points in each dimension. ; The default value is [1.0, 1.0, 1.0] ;SIZE: Set this keyword to a vector of values (one for each path ; point). These values are used to specify the width of the ; ribbon or the size of profile at each point along its path. ; This keyword is generally used to convey additional data ; parameters along the streamline. ;PROFILE: Set this keyword an array of 2D points which are treated as ; the cross section of the ribbon instead of a line segment. ; If the first and last points in the array are the same, a ; closed profile is generated. The profile is placed at each ; path vertex in the plane perpendicular to the line connecting ; each path vertex with the vertex normal defining the up ; direction. ; ; PROCEDURE/EXAMPLES: ; ; PARTICLE_TRACE, data, seeds, outverts, outconn, outnormals ; ; STREAMLINE, outverts, outconn, outnormals*width, outverts2, ; outconn2, PROFILE=[[-1, -1], [-1, 1], [1, 1], [1, -1], [-1,-1]] ; ; oStreamTubes = OBJ_NEW('IDLgrPolygon',outverts2,POLYGONS=outconn2) ; ; ; MODIFICATION HISTORY: ; KB, written Feb 1999. ;- PRO STREAMLINE,inverts,conn,normals,outverts,outconn, $ ANISOTROPY=anisotropy,PROFILE=profile, SIZE = sizevector dims = SIZE(inverts,/DIMENSIONS) if((N_ELEMENTS(dims) ne 2) or (dims[0] ne 3)) then $ MESSAGE,'VERTS must be a 3 x N array.' if(not KEYWORD_SET(anisotropy)) then anisotropy=[1.,1.,1.] bSize = 0 if(N_ELEMENTS(sizevector) eq dims[1]) then bSize = 1 verts = inverts verts[0,*] = verts[0,*]*anisotropy[0] verts[1,*] = verts[1,*]*anisotropy[1] verts[2,*] = verts[2,*]*anisotropy[2] nconn = N_ELEMENTS(conn) i=0UL noutconn=0UL nverts=0UL np = 0UL while((i lt nconn) and (np ge 0)) do begin np = conn[i] if(np gt 1) then begin nverts = nverts+2*np noutconn = noutconn+np-1 end i = i+np+1 end if(noutconn le 0) then return if(not KEYWORD_SET(profile)) then profile = [[0,0],[0,1]] pdims = SIZE(profile,/DIMENSIONS) npr = pdims[1] ;number of profile faces noutconn = noutconn*(npr-1)*8L nverts = nverts/2*npr outconn = ULONARR(noutconn) outverts = FLTARR(3,nverts) ;generate ribbon polygons and connectivity op=0UL i=0UL iverts=0UL voff=0UL prev = FLTARR(3,npr) while(i lt nconn) do begin np = conn[i] i=i+1 if(bSize) then useprofile = profile*sizevector[conn[i]] $ else useprofile = profile if(np gt 1) then begin for p=1UL,np-1 do begin if(p eq 1) then begin forward = verts[*,conn[i+1]]-verts[*,conn[i+0]] up0 = normals[*,conn[i+0]] side0 = -CROSSP(up0,forward) end forward = verts[*,conn[i+p]]-verts[*,conn[i+p-1]] up = normals[*,conn[i+p]] side = -CROSSP(up,forward) for pr=0,npr-2 do begin ;do each profile face if(pr eq 0) then begin if(p eq 1) then begin point0 = verts[*,conn[i+p-1]]+useprofile[0,pr]*side0 $ + useprofile[1,pr]*up0 outverts[*,0+voff]=point0 iverts = iverts+1 prev[*,pr] = point0 end else begin point0 = prev[*,pr] end point3 = verts[*,conn[i+p]]+useprofile[0,pr]*side $ + useprofile[1,pr]*up outverts[*,p*npr+voff]=point3 iverts = iverts+1 prev[*,pr] = point3 end else begin point0 = point1 point3 = point2 end if(p eq 1) then begin point1 = verts[*,conn[i+0]]+useprofile[0,pr+1]*side0 $ + useprofile[1,pr+1]*up0 outverts[*,pr+1+voff]=point1 iverts = iverts+1 prev[*,pr+1] = point1 end else begin point1 = prev[*,pr+1] end point2 = verts[*,conn[i+p]]+useprofile[0,pr+1]*side $ + useprofile[1,pr+1]*up prev[*,pr+1] = point2 outverts[*,p*npr+pr+1+voff]=point2 iverts = iverts+1 up0 = up side0 = side outconn[op]=3 ;upper left triangle outconn[op+1]=(p-1)*npr+pr+voff outconn[op+2]=outconn[op+1]+1 outconn[op+3]=outconn[op+1]+npr op = op+4 ;lower right triangle outconn[op]=3 outconn[op+1]=p*npr+pr+voff outconn[op+2]=outconn[op+1]-npr+1 outconn[op+3]=outconn[op+1]+1 op = op+4 end ;profile face end ;polyline voff = iverts i=i+np end else i=i+1 end ;conn END