PRO vu_planarcut, hdr, ff, ihdr=ihdr, ut0=ut0,  $
        radius      = radius        , $
        zoffset     = zoffset       , $
        type        = type          , $
        printer     = printer       , $
        silent      = silent        , $
        module      = module        , $
        body        = body          , $
        abg_euler   = abg_euler     , $
        degrees     = degrees       , $
        edge        = edge          , $
        circle      = circle        , $
        _extra      = _extra
    @compile_opt.pro        ; On error, return to caller
    @vu_fnc_include.pro     ;

InitVar, silent     , 0
InitVar, degrees    , /key

InitVar, printer    , /key
InitVar, fill       , /key
InitVar, earth      , /key
InitVar, circle     , /key

ihdr_set = IsType(ihdr, /defined)

utt = vu_getdata(hdr, ff, ut0=ut0, ihdr=ihdr, _extra=_extra, count=count, silent=silent+1)
IF count EQ 0 THEN RETURN

; utt determines the data matrix and is used to set the relation between
; the coordinate systems.

utt = Carrington(utt, /get_time)

say, TimeGet(utt,/ymd,upto=TimeUnit(/minute))+strcompress(ihdr), threshold=0, silent=silent

CASE ihdr_set OF
0: hdri = vu_gettime(hdr, ff, ut=utt, ff_ut=ffi)    ; Interpolate at time utt
1: hdri = vu_gettime(hdr, ff, ut=vu_get(hdr[ihdr], /uttime), ff_ut=ffi, /fixgrid); ihdr set explicitly
ENDCASE

IF IsType(edge,/defined) THEN BEGIN
    ;iedge = round( (edge-hdri.distance_start)/hdri.distance_step )
    ;ffi[*,*,iedge+1:*,*] = BadValue(ffi)

        iedge = round( (edge-vu_get(hdri,/start_distance))/vu_get(hdri,/distance_step) )+1
        IF 0 LE iedge AND iedge LT vu_get(hdri,/nrad) THEN ffi[*,*,iedge:*,*] = BadValue(ffi)

ENDIF


; Set up three unit vectors along x,y,z axes in the output frame
; (with z the normal to the plane, and x,y axes in the plane)
; The default output frame is the ecliptic seen from the north
; Then rotate these to the heliographic coordinate frame
; (z to heliographic north; x to heliographic longitude zero)

runit = [[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]]

; If abg_euler exists then apply that rotation first

IF IsType(abg_euler,/string) THEN BEGIN

    ; This is a fudge to allow making a planar cut through the orbital
    ; plane of a body whose orbital elements are stored in
    ; $EPHEM/orbits/orbital_elements.txt (mostly comets, I think).

    tmp_body = abg_euler
    tmp = strpos(tmp_body,'&')
    IF tmp NE -1 THEN tmp_body = strmid(tmp_body,tmp)

    tmp = filepath(root=getenv('EPHEM'),subdir='orbits','orbital_elements.txt')
    IF flt_read(tmp,mask=strjoin(replicate('1',20)),data,crumbs=crumbs,/double) THEN BEGIN
        crumbs = strtrim(reform(crumbs[0,*]))       ; Body name
        tmp = (where( strlowcase(tmp_body) EQ strlowcase(crumbs) ))[0]
        IF tmp NE -1 THEN BEGIN
            boost, body, abg_euler
            print, data[5:6,tmp]            ; Asc node and inclination
            abg_euler = [-90,-data[6,tmp],90-data[5,tmp]]/ToDegrees(degrees=degrees)
        ENDIF
    ENDIF

    IF IsType(abg_euler,/string) THEN destroyvar, abg_euler

ENDIF

IF IsType(abg_euler,/defined) THEN  $
    runit = EulerRotate(abg_euler, runit, degrees=degrees, /rectangular)

; Rotate to heliographic coordinates

runit = CvSky(utt, runit, _extra=_extra, /to_heliographic,  $
    euler_angles=euler_angles, /rectangular, degrees=degrees, euler_info=euler_info, silent=silent)

; If abg_euler exists combine it with the rotation to heliographic coordinates

IF IsType(abg_euler,/defined) THEN  $
    euler_angles = CombineRotations(abg_euler, euler_angles, degrees=degrees)

type = vu_type_insitu('planarcut', _extra=_extra, hdr=hdri, type=type)

FOR itype=0,n_elements(type)-1 DO BEGIN

    id = (where( type[itype].data ))[0]

    ; Extract fields from 'type' structure

    ctable  = type[itype].ctable
    Fmin    = type[itype].Fmin
    Fmax    = type[itype].Fmax
    display = type[itype].display
    label   = type[itype].label
    format  = type[itype].format
    charsize= type[itype].charsize
    xysize  = type[itype].xysize

    breakval= type[itype].breakval

    i = where(finite(breakval), nbreak)
    IF nbreak GT 0 THEN BEGIN
        breakval = type[itype].breakval[i]
        IF format EQ '' THEN breakval = round(breakval)
    ENDIF

    ; Done with 'type' structure
    ;===========================

    InitVar, radius , vu_get(hdr,/stop_distance)
    InitVar, zoffset, 0.0

    diameter = round(0.8*xysize[0])         ; Diameter of cross section in pixels
    diameter = (diameter-1)/2*2+1
                                            ; Rectangular 2D-vectors in plane of cross section
    rr = gridgen(diameter*[1,1], range=[-1.0,1.0,-1.0,1.0])
                                            ; Rectangular 3D-vectors in coordinate frame of data array
    rr = (zoffset*runit[*,2])#replicate(1,diameter*diameter)+radius*runit[*,0:1]#rr

    IF circle THEN outside = where(total(rr*rr,1) GT radius*radius)

    rr = cv_coord(from_rect=rr, /to_sphere) ; Convert to spherical coordinates
    rr[0,*] = AngleRange(rr[0,*])           ; Keep inside [0,2*!pi]

    xci = vu_get(hdri, /array_range   )
    rri = vu_get(hdri, /start_distance)
    dri = vu_get(hdri, /distance_step )
    tti = vu_get(hdri, /uttime        )

    zz = vu_atlocation(xci,rri,dri, vu_fnc(id,ffi,/t3d_array),  $
        sequence=tti, location=rr, times=tti, /cv2carrington, /periodic)

    zz = reform(zz, diameter, diameter, /overwrite)
    IF circle THEN IF outside[0] NE -1 THEN zz[outside] = BadValue(zz)

    old_device = !D.name                    ; Store current plot device

    set_page, $
        zbuffer     = 1-printer     , $
        printer     = printer       , $
        /silent                     , $
        xysize      = xysize        , $
        fullsize    = printer       , $
        old_device  = old_device    , $
        ctable      = ctable        , $
        _extra      = _extra

    title  = vu_fnc(id,/symbol,/norm)
    title += ' ('+vu_fnc(id,/unit)+')'

    PlotPlanarCut, zz, ut=utt       , $
        radius      = radius        , $
        euler_angles= euler_angles  , $
        degrees     = degrees       , $ 
        euler_info  = euler_info    , $
        earth       = earth         , $
        breakval    = breakval      , $
        charsize    = charsize      , $
        title       = title         , $
        body        = body          , $
        _extra      = _extra

    if (istype(module, /undefined) or (n_elements(type) eq 2)) then begin
        if (istype(module, /defined) and (n_elements(type) eq 2) and (itype eq 0)) then destroyvar, module
        boost, module, display + label
    end
   
        
    vu_get_page, hdri, title='', module[itype], ut=utt, device=old_device,  $
        silent=silent, new=itype ne 0, _extra=_extra

ENDFOR

RETURN  &  END