visad/src/main/java/ucar/nc2/iosp/grid/GridHorizCoordSys.java
private void makeCurvilinearAxis( NetcdfFile ncfile ) {

    List<Variable> vars = ncfile.getRootGroup().getVariables();
    String latpp = null, lonpp = null, latU = null, lonU = null, latV = null, lonV = null;
    // has to be done twice because there's no guarantee that the
    // coordinate variables will be accessed first
    List<String> timeDimLL = new ArrayList<>();
    List<String> timeDimV = new ArrayList<>();
    for( Variable var : vars ) {
      if( var.getShortName().startsWith( "Latitude") ) {
        // remove time dependency
        int[] shape = var.getShape();
        if (var.getRank() == 3 && shape[0] == 1) { // remove time dependencies - MAJOR KLUDGE
              List<Dimension> dims = var.getDimensions();
              if( ! timeDimLL.contains( dims.get( 0 ).getShortName() ))
                timeDimLL.add( dims.get( 0 ).getShortName() );
              dims.remove(0);
              var.setDimensions(dims);
        }
        // add lat attributes
        var.addAttribute(new Attribute("units", "degrees_north"));
        var.addAttribute(new Attribute("long_name", "latitude coordinate"));
        var.addAttribute(new Attribute("standard_name", "latitude"));
        var.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.Lat.toString()));
        if( var.getShortName().contains( "U_Wind_Component")) {
          latU = var.getFullName();
        } else if( var.getShortName().contains( "V_Wind_Component")) {
          latV = var.getFullName();
        } else {
          latpp = var.getFullName();
        }

      } else if( var.getShortName().startsWith( "Longitude" )) {
        // remove time dependency
        int[] shape = var.getShape();
        if (var.getRank() == 3 && shape[0] == 1) { // remove time dependencies - MAJOR KLUDGE
              List<Dimension> dims = var.getDimensions();
              if( ! timeDimLL.contains( dims.get( 0 ).getShortName() ))
                timeDimLL.add( dims.get( 0 ).getShortName() );
              dims.remove(0);
              var.setDimensions(dims);
        }
        // add lon attributes
        var.addAttribute(new Attribute("units", "degrees_east"));
        var.addAttribute(new Attribute("long_name", "longitude coordinate"));
        var.addAttribute(new Attribute("standard_name", "longitude"));
        var.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.Lon.toString()));

        if( var.getShortName().contains( "U_Wind_Component")) {
          lonU = var.getFullName();
        } else if( var.getShortName().contains( "V_Wind_Component")) {
          lonV = var.getFullName();
        } else {
          lonpp = var.getFullName();
        }
      }
   }

   // add coordinates attribute to variables
   for( Variable var : vars ) {
     List<Dimension> dims = var.getDimensions();
     if( var.getShortName().startsWith( "U-component") ) {
        var.addAttribute(new Attribute("coordinates", latU +" "+ lonU));
        if( ! timeDimV.contains( dims.get( 0 ).getShortName() ))
                timeDimV.add( dims.get( 0 ).getShortName() );
      } else if( var.getShortName().startsWith( "V-component") ) {
        var.addAttribute(new Attribute("coordinates", latV +" "+ lonV));
        if( ! timeDimV.contains( dims.get( 0 ).getShortName() ))
                timeDimV.add( dims.get( 0 ).getShortName() );

        // rest of variables default to Pressure_Point
      } else {
        var.addAttribute(new Attribute("coordinates", latpp +" "+ lonpp));
        if( ! timeDimV.contains( dims.get( 0 ).getShortName() ))
                timeDimV.add( dims.get( 0 ).getShortName() );
     }
    }

    /* remove Latitude/Longitude time dimension and variable if possible
    for( String tdLL : timeDimLL) {
      if( timeDimV.contains( tdLL ))
        continue;
      // else only used with Lat/Lon
      ncfile.getRootGroup().removeDimension( tdLL );
      ncfile.getRootGroup().removeVariable( tdLL );
    } */

  }
private void makeCurvilinearAxis( NetcdfFile ncfile ) {

    List<Variable> vars = ncfile.getRootGroup().getVariables();
    String latpp = null, lonpp = null, latU = null, lonU = null, latV = null, lonV = null;
    // has to be done twice because there's no guarantee that the
    // coordinate variables will be accessed first
    List<String> timeDimLL = new ArrayList<>();
    List<String> timeDimV = new ArrayList<>();
    for( Variable var : vars ) {
      if( var.getShortName().startsWith( "Latitude") ) {
        // remove time dependency
        int[] shape = var.getShape();
        if (var.getRank() == 3 && shape[0] == 1) { // remove time dependencies - MAJOR KLUDGE
              List<Dimension> dims = var.getDimensions();
              if( ! timeDimLL.contains( dims.get( 0 ).getShortName() ))
                timeDimLL.add( dims.get( 0 ).getShortName() );
              dims.remove(0);
              var.setDimensions(dims);
        }
        // add lat attributes
        var.addAttribute(new Attribute("units", "degrees_north"));
        var.addAttribute(new Attribute("long_name", "latitude coordinate"));
        var.addAttribute(new Attribute("standard_name", "latitude"));
        var.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.Lat.toString()));
        if( var.getShortName().contains( "U_Wind_Component")) {
          latU = var.getFullName();
        } else if( var.getShortName().contains( "V_Wind_Component")) {
          latV = var.getFullName();
        } else {
          latpp = var.getFullName();
        }

      } else if( var.getShortName().startsWith( "Longitude" )) {
        // remove time dependency
        int[] shape = var.getShape();
        if (var.getRank() == 3 && shape[0] == 1) { // remove time dependencies - MAJOR KLUDGE
              List<Dimension> dims = var.getDimensions();
              if( ! timeDimLL.contains( dims.get( 0 ).getShortName() ))
                timeDimLL.add( dims.get( 0 ).getShortName() );
              dims.remove(0);
              var.setDimensions(dims);
        }
        // add lon attributes
        var.addAttribute(new Attribute("units", "degrees_east"));
        var.addAttribute(new Attribute("long_name", "longitude coordinate"));
        var.addAttribute(new Attribute("standard_name", "longitude"));
        var.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.Lon.toString()));

        if( var.getShortName().contains( "U_Wind_Component")) {
          lonU = var.getFullName();
        } else if( var.getShortName().contains( "V_Wind_Component")) {
          lonV = var.getFullName();
        } else {
          lonpp = var.getFullName();
        }
      }
   }

   // add coordinates attribute to variables
   for( Variable var : vars ) {
     List<Dimension> dims = var.getDimensions();
     if( var.getShortName().startsWith( "U-component") ) {
        var.addAttribute(new Attribute("coordinates", latU +" "+ lonU));
        if( ! timeDimV.contains( dims.get( 0 ).getShortName() ))
                timeDimV.add( dims.get( 0 ).getShortName() );
      } else if( var.getShortName().startsWith( "V-component") ) {
        var.addAttribute(new Attribute("coordinates", latV +" "+ lonV));
        if( ! timeDimV.contains( dims.get( 0 ).getShortName() ))
                timeDimV.add( dims.get( 0 ).getShortName() );

        // rest of variables default to Pressure_Point
      } else {
        var.addAttribute(new Attribute("coordinates", latpp +" "+ lonpp));
        if( ! timeDimV.contains( dims.get( 0 ).getShortName() ))
                timeDimV.add( dims.get( 0 ).getShortName() );
     }
    }

    /* remove Latitude/Longitude time dimension and variable if possible
    for( String tdLL : timeDimLL) {
      if( timeDimV.contains( tdLL ))
        continue;
      // else only used with Lat/Lon
      ncfile.getRootGroup().removeDimension( tdLL );
      ncfile.getRootGroup().removeVariable( tdLL );
    } */

  }
private void makeCurvilinearAxis ( NetcdfFile ncfile ) { List < Variable > vars = ncfile . getRootGroup ( ) . getVariables ( ) ; String latpp = null , lonpp = null , latU = null , lonU = null , latV = null , lonV = null ; // has to be done twice because there's no guarantee that the // coordinate variables will be accessed first List < String > timeDimLL = new ArrayList <> ( ) ; List < String > timeDimV = new ArrayList <> ( ) ; for ( Variable var : vars ) { if ( var . getShortName ( ) . startsWith ( "Latitude" ) ) { // remove time dependency int [ ] shape = var . getShape ( ) ; if ( var . getRank ( ) == 3 && shape [ 0 ] == 1 ) { // remove time dependencies - MAJOR KLUDGE List < Dimension > dims = var . getDimensions ( ) ; if ( ! timeDimLL . contains ( dims . get ( 0 ) . getShortName ( ) ) ) timeDimLL . add ( dims . get ( 0 ) . getShortName ( ) ) ; dims . remove ( 0 ) ; var . setDimensions ( dims ) ; } // add lat attributes var . addAttribute ( new Attribute ( "units" , "degrees_north" ) ) ; var . addAttribute ( new Attribute ( "long_name" , "latitude coordinate" ) ) ; var . addAttribute ( new Attribute ( "standard_name" , "latitude" ) ) ; var . addAttribute ( new Attribute ( _Coordinate . AxisType , AxisType . Lat . toString ( ) ) ) ; if ( var . getShortName ( ) . contains ( "U_Wind_Component" ) ) { latU = var . getFullName ( ) ; } else if ( var . getShortName ( ) . contains ( "V_Wind_Component" ) ) { latV = var . getFullName ( ) ; } else { latpp = var . getFullName ( ) ; } } else if ( var . getShortName ( ) . startsWith ( "Longitude" ) ) { // remove time dependency int [ ] shape = var . getShape ( ) ; if ( var . getRank ( ) == 3 && shape [ 0 ] == 1 ) { // remove time dependencies - MAJOR KLUDGE List < Dimension > dims = var . getDimensions ( ) ; if ( ! timeDimLL . contains ( dims . get ( 0 ) . getShortName ( ) ) ) timeDimLL . add ( dims . get ( 0 ) . getShortName ( ) ) ; dims . remove ( 0 ) ; var . setDimensions ( dims ) ; } // add lon attributes var . addAttribute ( new Attribute ( "units" , "degrees_east" ) ) ; var . addAttribute ( new Attribute ( "long_name" , "longitude coordinate" ) ) ; var . addAttribute ( new Attribute ( "standard_name" , "longitude" ) ) ; var . addAttribute ( new Attribute ( _Coordinate . AxisType , AxisType . Lon . toString ( ) ) ) ; if ( var . getShortName ( ) . contains ( "U_Wind_Component" ) ) { lonU = var . getFullName ( ) ; } else if ( var . getShortName ( ) . contains ( "V_Wind_Component" ) ) { lonV = var . getFullName ( ) ; } else { lonpp = var . getFullName ( ) ; } } } // add coordinates attribute to variables for ( Variable var : vars ) { List < Dimension > dims = var . getDimensions ( ) ; if ( var . getShortName ( ) . startsWith ( "U-component" ) ) { var . addAttribute ( new Attribute ( "coordinates" , latU + " " + lonU ) ) ; if ( ! timeDimV . contains ( dims . get ( 0 ) . getShortName ( ) ) ) timeDimV . add ( dims . get ( 0 ) . getShortName ( ) ) ; } else if ( var . getShortName ( ) . startsWith ( "V-component" ) ) { var . addAttribute ( new Attribute ( "coordinates" , latV + " " + lonV ) ) ; if ( ! timeDimV . contains ( dims . get ( 0 ) . getShortName ( ) ) ) timeDimV . add ( dims . get ( 0 ) . getShortName ( ) ) ; // rest of variables default to Pressure_Point } else { var . addAttribute ( new Attribute ( "coordinates" , latpp + " " + lonpp ) ) ; if ( ! timeDimV . contains ( dims . get ( 0 ) . getShortName ( ) ) ) timeDimV . add ( dims . get ( 0 ) . getShortName ( ) ) ; } } /* remove Latitude/Longitude time dimension and variable if possible
    for( String tdLL : timeDimLL) {
      if( timeDimV.contains( tdLL ))
        continue;
      // else only used with Lat/Lon
      ncfile.getRootGroup().removeDimension( tdLL );
      ncfile.getRootGroup().removeVariable( tdLL );
    } */ }
CurvilinearAxis

Make lat/lon axis from variables that start with Latitude/Longitude and then
add the coordinates to the variables. This code is based on the ofs_atl files
received from Rich Signell. This code is rigid because it expects coordinate names
to start with Latitude/Longitude and other coordinate of depth.
@param ncfile  NetcdfFile
CurvilinearAxis