0

これは、現時点でチャートに線を追加する方法です。これは、表示したい任意の関数の抽象クラスです。

public abstract class ArbitraryFunction implements
    ValueProvider<ArbitraryFunctionData, Double> {

  private String field;

  public abstract Double f(Double x);

  /**
   * Constructor
   */
  public ArbitraryFunction(String field) {
    this.field = field;
  }

  @Override
  public Double getValue(ArbitraryFunctionData object) {
    return object.get(field);
  }

  @Override
  public void setValue(ArbitraryFunctionData object, Double value) {
    object.put(field, value);
  }

  @Override
  public String getPath() {
    return field;
  }
}

チャートの作成方法は次のとおりです。

ArbitraryFunction f1 = new ArbitraryFunction("f1") {
      @Override
      public Double f(Double x) {
        return Math.sin(x);
      }
    };

functionMap.put(f1.getPath(), f1);

// collects the data of the functions and adds them to the store
for (Double x = 0.0; x <= 2 * Math.PI; x = x + 0.1) {
  ArbitraryFunctionData d = new ArbitraryFunctionData();
  d.setName("" + x);
  for (Map.Entry<String, ArbitraryFunction> entry : functionMap.entrySet()) {
    ArbitraryFunction tmp = entry.getValue();
    d.put(tmp.getPath(), tmp.f(x));
  }
  store.add(d);
}

chart.setStore(store);

verticalAxis.setPosition(Position.LEFT);
verticalAxis.addField(f1);
verticalAxis.setSteps(2);
verticalAxis.setMinorTickSteps(5);
chart.addAxis(verticalAxis);

これは意図したとおりに機能します。グラフは私の線を正しく示しており、縦軸も正しいです。しかし、何を与える必要があるのか​​わからないため、横軸を描くのに問題がありますhorizontalAxis.addField( ??? )。私はいくつかのことを試しましたが、何もうまくいきませんでした。

横軸を設定する方法を知っている人はいますか?

4

1 に答える 1

1

横軸の値を何にしますか? それは別の NumericAxis ですか - 各データ ポイントにはx描画する必要がある値がありますか? dループ内のそれぞれには文字列nameといくつかの値があります。おそらく、CategoryAxis<ArbitraryFunctionData, String>それらの値を描画するだけの が必要nameですか?


以前に誤解していたようです-関数オブジェクトは、データのプロット方法を変更するのではなく、セットアップで使用されるだけです

あなたが何を求めているのかはまだわかりませんが、主にいくつかの行をプロットしたいようです。各データ ポイント (ArbitraryFunctionData?) は、使用されている各関数の Y 値とタイトルを持っているようですが、X 値はありません。名前、Y) CategoryAxis と NumericAxis を使用します。これは多かれ少なかれこのサンプルのようになります: http://www.sencha.com/examples/#ExamplePlace:linechart - 下に文字列、横に数字。

ここに 1 つを取り上げます。主に、既に持っているアイデア/構造から構築します。

public class FunctionPlotter implements EntryPoint {
  public static class ArbitraryFunctionData {
    private double xValue;
    private Map<String, Double> yValues = new HashMap<String, Double>();
    public double get(String key) {
      return yValues.get(key);
    }
    public void put(String key, double yValue) {
      yValues.put(key, yValue);
    }
    public double getXValue() {
      return xValue;
    }
    public void setxValue(double xValue) {
      this.xValue = xValue;
    }
  }
  public interface AFDProperties extends PropertyAccess<ArbitraryFunctionData> {
    //xvalue is unique, key off of that
    @Path("xValue")
    ModelKeyProvider<ArbitraryFunctionData> key();

    //automatic ValueProvider generation for the get/setXValue methods
    ValueProvider<ArbitraryFunctionData, Double> xValue();
  }

  /** 
   * This is really doing two different jobs at once - wasn't quite was I was trying to suggest in 
   * that other question. See the second version of this for clarification...
   */
  public static abstract class ArbitraryFunction implements ValueProvider<ArbitraryFunctionData, Double> {
    private final String field;

    public ArbitraryFunction(String field) {
      this.field = field;
    }

    public abstract Double f(Double x);

    @Override
    public Double getValue(ArbitraryFunctionData object) {
      return object.get(field);
    }

    @Override
    public void setValue(ArbitraryFunctionData object, Double value) {
      object.put(field, value);
    }

    @Override
    public String getPath() {
      return field;
    }
  }

  @Override
  public void onModuleLoad() {
    Viewport vp = new Viewport();

    Set<ArbitraryFunction> functions = new HashSet<ArbitraryFunction>();
    ArbitraryFunction f1 = new ArbitraryFunction("f1") {
      @Override
      public Double f(Double x) {
        return Math.sin(x);
      }
    };
    functions.add(f1);

    AFDProperties props = GWT.create(AFDProperties.class);
    ListStore<ArbitraryFunctionData> store = new ListStore<ArbitraryFunctionData>(props.key());
    // collects the data of the functions and adds them to the store
    for (Double x = 0.0; x <= 2 * Math.PI; x = x + 0.1) {
      // Create one data object, and set the X value, since that is the same for all Y values
      ArbitraryFunctionData d = new ArbitraryFunctionData();
      d.setxValue(x);

      // For each function, set the corresponding Y value
      for (ArbitraryFunction func : functions) {
        d.put(func.getPath(), func.f(x));
      }
      store.add(d);
    }

    Chart<ArbitraryFunctionData> chart = new Chart<ArbitraryFunctionData>();
    chart.setStore(store);

    //Y-axis
    NumericAxis<ArbitraryFunctionData> verticalAxis = new NumericAxis<ArbitraryFunctionData>();
    verticalAxis.setPosition(Position.LEFT);
    verticalAxis.addField(f1);//needs to know this field to properly set the range of values
    //f2, f3, etc
    verticalAxis.setSteps(2);
    verticalAxis.setMinorTickSteps(5);
    chart.addAxis(verticalAxis);

    // X-Axis, this time reading from the xValue, not the series of ValueProviders
    NumericAxis<ArbitraryFunctionData> horizAxis = new NumericAxis<ArbitraryFunctionData>();
    horizAxis.setPosition(Position.BOTTOM);
    horizAxis.addField(props.xValue());//same value for all
    horizAxis.setSteps(2);
    horizAxis.setMinorTickSteps(5);
    chart.addAxis(horizAxis);

    for (ArbitraryFunction func : functions) {
      LineSeries<ArbitraryFunctionData> line = new LineSeries<ArbitraryFunctionData>();
      // configure x axis
      line.setXAxisPosition(Position.BOTTOM);//where is it
      line.setXField(props.xValue());//what value do i use
      // configure y axis
      line.setYAxisPosition(Position.LEFT);//where is it
      line.setYField(func);//what value do i use

      //probably want to customized per func
      line.setStroke(RGB.GRAY);
      line.setStrokeWidth(2);

      chart.addSeries(line);
    }

    vp.setWidget(chart);
    RootPanel.get().add(vp);
  }
}

ここでは 2 つ取り上げます。今回ははるかに単純なデータを使用し、関数を独自の ValueProvider にして、データの汚れを単純に保ちます。ValueProvider関数であり、getValue を自分で呼び出すことはなく、軸/シリーズに任せることに注意してください。実際に機能することを示すために、ここに 2 番目の関数を追加しました。

public class FunctionPlotter implements EntryPoint {

  /**
   * Where did everything go? We're just making a ValueProvider now that can handle 
   * each number as a value, and working out the details from there
   *
   * For fun, added per-function coloring too
   */
  public abstract static class Function implements ValueProvider<Double, Double> {
    private final String name;
    private final Color color;
    public Function(String name, Color color) {
      this.name = name;
      this.color = color;
    }
    @Override
    public abstract Double getValue(Double object);

    @Override
    public String getPath() {
      return name;
    }
    @Override
    public void setValue(Double object, Double value) {
      //no-op
    }
    public Color getColor() {
      return color;
    }
  }

  @Override
  public void onModuleLoad() {
    Viewport vp = new Viewport();

    Set<Function> functions = new HashSet<Function>();
    Function f1 = new Function("f1", RGB.RED) {
      @Override
      public Double getValue(Double x) {
        return Math.sin(x);
      }
    };
    functions.add(f1);
    Function f2 = new Function("f2", RGB.BLACK) {
      @Override
      public Double getValue(Double x) {
        return Math.cos(x);
      }
    };
    functions.add(f2);

    //Turns out Stores can hold any objects - should probably factor out this key provider for reuse...
    ListStore<Double> store = new ListStore<Double>(new ModelKeyProvider<Double>() {
      @Override
      public String getKey(Double item) {
        return item.toString();
      }
    });
    // collects the data of the functions and adds them to the store
    for (Double x = 0.0; x <= 2 * Math.PI; x = x + 0.1) {
      store.add(x);
    }

    Chart<Double> chart = new Chart<Double>();
    chart.setStore(store);

    //Y-axis
    NumericAxis<Double> verticalAxis = new NumericAxis<Double>();
    verticalAxis.setPosition(Position.LEFT);
    for (Function func : functions) {
      verticalAxis.addField(func);//needs to know this field to properly set the range of values
    }
    verticalAxis.setSteps(2);
    verticalAxis.setMinorTickSteps(5);
    chart.addAxis(verticalAxis);

    // X-Axis, this time reading from the xValue, not the series of ValueProviders
    NumericAxis<Double> horizAxis = new NumericAxis<Double>();
    horizAxis.setPosition(Position.BOTTOM);
    horizAxis.addField(new IdentityValueProvider<Double>());//magic value provider that returns the same string
    horizAxis.setSteps(2);
    horizAxis.setMinorTickSteps(5);
    chart.addAxis(horizAxis);

    for (Function func : functions) {
      LineSeries<Double> line = new LineSeries<Double>();
      // configure x axis
      line.setXAxisPosition(Position.BOTTOM);//where is it
      line.setXField(new IdentityValueProvider<Double>());//what value do i use
      // configure y axis
      line.setYAxisPosition(Position.LEFT);//where is it
      line.setYField(func);//what value do i use

      //probably want to customized per func
      line.setStroke(func.getColor());
      line.setStrokeWidth(2);

      chart.addSeries(line);
    }

    vp.setWidget(chart);
    RootPanel.get().add(vp);
  }
}
于 2013-03-29T16:25:09.323 に答える