Delaunay and Boundaries

Greetings,

I'm trying to plot values at specific points between to boundaries. If you look at:

http://www.cimms.ou.edu/~kmanross/VCPRPE/VisADSamples/Gridded2DSet.gif

You can see that I have been able to get the points and set them up in a Gridded2DSet(MathType, samples[][], NUM_POINTS, 1). (Note this area is not "filled" - if you zoom in, you will see individual points.)

Since this is an irregular shape, I also tried creating an Irregular2DSet from the same points. The Irregular2DSet follows the bottom boundary fairly well, but does not do so well with the top boundary.

Please see:

http://www.cimms.ou.edu/~kmanross/VCPRPE/VisADSamples/Delaunay.gif

Why is there such a discrepancy between the way the Delaunay fits to the bottom boundary and the way it doesn't fit the top boundary?

I would like to

A) Get the Irregular2DSet to follow the top boundary as well as it does the bottom

or

B) Possibly use a Gridded2DSet (man dim = 2).

Can I do B given the irregularity of the data. (I have 28700 points arranged in 400 columns = 71.75 rows?)

Here is my test program:


import java.*;
import java.awt.*;
import java.awt.event.*;
import java.rmi.RemoteException;
import java.util.Vector;

import javax.swing.*;
import javax.swing.event.*;

import visad.*;
import visad.java3d.DisplayImplJ3D;
import visad.java3d.TwoDDisplayRendererJ3D;
import visad.data.units.*;

public class rangeHeightGridTest extends JPanel implements ActionListener
{

  private DisplayImpl display;
  private RealType ran, ht;
  private RealTupleType ranHt_tt;
  private ScalarMap ranMap, htMap;
  private DataReferenceImpl dataRef;
  private Unit kilometer, km;
  private double[] projMatrix;
  private JButton reset = new JButton("Reset");

  final static double INDEX_OF_REFRACTION = (4.0/3.0);
  final static double EARTH_RADIUS = 6378; // km at Equator
  final static double RADIANS = (Math.PI/180);


  public rangeHeightGridTest() throws VisADException, RemoteException
  {

    reset.addActionListener(this);

    try
    { kilometer = Parser.parse("kilometer").clone("km"); }
    catch (ParseException P)
    { System.out.println("ParseException: " + P); }
    catch (UnitException U)
    { System.out.println("UnitException: " + U); }


    ran = RealType.getRealType("range", km, null);
    ht = RealType.getRealType("height", km, null);
    RealType value = RealType.getRealType("value", null, null);

    RealTupleType ranHt_tt = new RealTupleType(ran, ht);

    ranMap = new ScalarMap(ran, Display.XAxis);
    htMap = new ScalarMap(ht, Display.YAxis);
    ScalarMap valueMap = new ScalarMap(value, Display.RGB);

    htMap.setRange(0.0, 25.0);

display = new DisplayImplJ3D( "TextDisplay", new TwoDDisplayRendererJ3D() );
    display.addMap(ranMap);
    display.addMap(htMap);
    display.addMap(valueMap);

    ConstantMap[] setMap = { new ConstantMap (1.0f, Display.Red),
                                  new ConstantMap (0.0f, Display.Green),
                                  new ConstantMap (0.0f, Display.Blue) };

    ConstantMap[] ffMap = { new ConstantMap (0.0f, Display.Red),
                                  new ConstantMap (0.0f, Display.Green),
                                  new ConstantMap (1.0f, Display.Blue) };

    ConstantMap[] pointMap = { new ConstantMap (0.0f, Display.Red),
                                  new ConstantMap (0.0f, Display.Green),
                                  new ConstantMap (0.0f, Display.Blue),
new ConstantMap (0.1f, Display.PointSize) };


    ProjectionControl initPC = display.getProjectionControl();
    projMatrix = initPC.getMatrix();
    GraphicsModeControl gmc = display.getGraphicsModeControl();
    gmc.setScaleEnable(true);

    //  ##### Create two beampaths using FlatFields
    float[][] beamPath1 = calcBeamPath(0.00, 400.0, 100.0);
    float[][] ranVals1 = new float[1][];
    float[][] htVals1 = new float[1][];
    ranVals1[0] = beamPath1[0];
    htVals1[0] = beamPath1[1];
    Irregular1DSet ranSet1 = new Irregular1DSet(ran, ranVals1);
    FunctionType ranHt_func1 = new FunctionType(ran, ht);
    FlatField ranHt_ff1 = new FlatField(ranHt_func1, ranSet1);
    ranHt_ff1.setSamples(htVals1);

    float[][] beamPath2 = calcBeamPath(1.00, 400.0, 100.0);
    float[][] ranVals2 = new float[1][];
    float[][] htVals2 = new float[1][];
    ranVals2[0] = beamPath2[0];
    htVals2[0] = beamPath2[1];
    Irregular1DSet ranSet2 = new Irregular1DSet(ran, ranVals2);
    FunctionType ranHt_func2 = new FunctionType(ran, ht);
    FlatField ranHt_ff2 = new FlatField(ranHt_func2, ranSet2);
    ranHt_ff2.setSamples(htVals2);

// ##### This first loop is to get the number of points needed to initialize // ##### the "ranHtVals" array. (I'm sure there is an easier way to do this)
    int total = 0;
    int numPoints = 0;
    for (int j = 1; j < 400; j++)
    {
      Real ranIndex = new Real(ran, j);
//System.out.println("Ht1 at ran: " + ranIndex + " is: " + ranHt_ff1.evaluate(ranIndex) ); //System.out.println("Ht2 at ran: " + ranIndex + " is: " + ranHt_ff2.evaluate(ranIndex) );

      Real realTop = (Real)ranHt_ff2.evaluate(ranIndex);
      Real realBottom = (Real)ranHt_ff1.evaluate(ranIndex);

      float top = (float) realTop.getValue();
      float bottom = (float) realBottom.getValue();

      float heightDiff = top - bottom;
      if (heightDiff < 0.05)
      { numPoints = 1; }
      else
      { numPoints = Math.round((float) (heightDiff / 0.05f));}
      float width = (float) (heightDiff / numPoints);


//System.out.println(j +"): Top: " + top + ", Bottom: " + bottom + ", Diff: " // + heightDiff + ", Points: " + numPoints + ", boxWidth: " + width);
      //  System.out.println(j + "): boxWidth: " + width);
      total = total + numPoints + 2;
    }

    float[][] ranHtVals = new float[2][total];
    float[][] valueVals = new float[1][total];
    int index = 0;
    for (int j = 1; j < 400; j++)
    {
      Real ranIndex = new Real(ran, j);

      Real realTop = (Real)ranHt_ff2.evaluate(ranIndex);
      Real realBottom = (Real)ranHt_ff1.evaluate(ranIndex);

      float top = (float) realTop.getValue();
      float bottom = (float) realBottom.getValue();

      float heightDiff = top - bottom;
      if (heightDiff < 0.05)
      { numPoints = 1; }
      else
      { numPoints = Math.round((float) (heightDiff / 0.05f)); }
      float width = (float) (heightDiff / numPoints);

      for (int i = 0; i < numPoints+2; i++)
      {
        ranHtVals[0][index] = (float)ranIndex.getValue();

        if (i == 0)
        { ranHtVals[1][index] = (float) (top); }
        if (i == numPoints+1)
        { ranHtVals[1][index] = (float) (bottom); }
        else
        { ranHtVals[1][index] = (float) (top - width * i); }

        valueVals[0][index] = (float)((top - width * i) - bottom);
        index++;
      }
    }



// ##### To view difference in plotting, uncomment this section and comment out the next section

/*
    // ###### Section 1
    Irregular2DSet iSet = new Irregular2DSet(ranHt_tt, ranHtVals);
    DataReferenceImpl iSetRef = new DataReferenceImpl("iSetRef");
    iSetRef.setData(iSet);
    display.addReference(iSetRef);
*/

// ##### To view difference in plotting, comment this section and uncomment the previous section

    // ###### Section 2
    Gridded2DSet loadem = new Gridded2DSet(ranHt_tt, ranHtVals, total, 1);
    DataReferenceImpl setRef = new DataReferenceImpl("setRef");
    display.addReference(setRef);
    setRef.setData(loadem);




    DataReferenceImpl ffRef1 = new DataReferenceImpl("ffRef1");
    display.addReference(ffRef1, ffMap);
    ffRef1.setData(ranHt_ff1);
    DataReferenceImpl ffRef2 = new DataReferenceImpl("ffRef2");
    display.addReference(ffRef2, setMap);
    ffRef2.setData(ranHt_ff2);


    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    setAlignmentY(JPanel.TOP_ALIGNMENT);
    setAlignmentX(JPanel.LEFT_ALIGNMENT);
    Component comp = display.getComponent();
    ((JComponent)comp).setPreferredSize( new Dimension(500,500) );


    add(comp);
    add(reset);

  }

  public void actionPerformed(ActionEvent e)
  { resetOrientation(); }


  /**
   * Resets the display projection to its original value.
   * Borrowed from VisAD SpreadSheet
   */
  public void resetOrientation() {
    if (display != null) {
      ProjectionControl pc = display.getProjectionControl();
      if (pc != null) {
        try {
          pc.setMatrix(projMatrix);
        }
        catch (VisADException exc) {
          System.out.println("Cannot reset orientation" + exc);
        }
        catch (RemoteException exc) {
          System.out.println("Cannot reset orientation" + exc);
        }
      }
    }
  }

public float[][] calcBeamPath(double elevAngle, double maxRange, double radarElevation) throws VisADException, RemoteException
  {
    double MAX_RANGE = maxRange;
    int BEAMPATHSAMPLING = 400;
    double E_ANGLE = elevAngle * RADIANS;
    double EFFECTIVE_EARTH_RADIUS = INDEX_OF_REFRACTION * EARTH_RADIUS;

    Vector h = new Vector();
    Vector r = new Vector();

    float[][] heightVals;
    float[][] rangeVals;

Linear1DSet r_set = new Linear1DSet(0.0, maxRange+10.0, BEAMPATHSAMPLING);
    float[][] slantRange = r_set.getSamples(true);
    Irregular1DSet rangeSet;
    FlatField beamPath_ff;
    FunctionType rangeHeightFunc = new FunctionType(ran, ht);

    for (int i = 0; i < BEAMPATHSAMPLING; i++)
    {
double inside = ((Math.pow(slantRange[0][i],2)) + (Math.pow(EFFECTIVE_EARTH_RADIUS,2)) + (2*slantRange[0][i]*EFFECTIVE_EARTH_RADIUS*Math.sin(E_ANGLE)));
      double outside = EFFECTIVE_EARTH_RADIUS;
Float n = new Float( (float)( (radarElevation/1000) + ((Math.pow(inside,0.5)) - outside)) );
      h.add(n);

      double numer = (slantRange[0][i]*Math.cos(E_ANGLE));
      double denom = (EFFECTIVE_EARTH_RADIUS + n.floatValue() );
      double quo = (numer/denom);
Float o = new Float( (float)(EFFECTIVE_EARTH_RADIUS*Math.asin(quo)) );
      r.add(o);

      if (n.floatValue() > 25.0)
      { break; }

      else if (o.floatValue() > MAX_RANGE)
      { break; }

    }

    float[][] rangeAndHeight = new float[2][r.size()];

    Float[] e = (Float[]) h.toArray(new Float[h.size()]);
    Float[] f = (Float[]) r.toArray(new Float[r.size()]);
    for (int g = 0; g < h.size(); g++)
    {
      rangeAndHeight[0][g] = f[g].floatValue();
      rangeAndHeight[1][g] = e[g].floatValue();
    }

    return rangeAndHeight;
  }


public static void main(String[] args) throws VisADException, RemoteException
  {
    JFrame frame = new JFrame("First VisAd Example");
    rangeHeightGridTest me = new rangeHeightGridTest();

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(me);
    frame.pack();
    frame.setVisible(true);
  }


}

--
+------------------------------------------------------------+
Kevin L. Manross        [KD5MYD] <><          (405)-366-0557
CIMMS Research Associate               kevin.manross@xxxxxxxx
[NSSL-WRDD/SWATN]           http://www.cimms.ou.edu/~kmanross

"My opinions are my own and not representative of CIMMS, NSSL,
 NOAA or any affiliates"
+------------------------------------------------------------+