3

私がこれを持っているとしましょうXYSeries

XYSeries temps = new XYSeries("Temperature");
temps.add(0, 43);
temps.add(1, 42);
temps.add(2, 40);
temps.add(3, 38);
temps.add(4, 35);
temps.add(5, 35);
temps.add(6, 34);
temps.add(7, 33);
temps.add(8, 32);
temps.add(9, 32);

レンダリングされた場合、これは10時間の温度をグラフ化します。

このシリーズの各データポイントの画面のx位置を取得するにはどうすればよいですか?つまり、6番目のデータポイントが画面上のどこにあるかをどのように見つけることができますか?

私がやろうとしているのは、データポイントの詳細を表示できるように、ユーザーが画面に触れた場所に最も近い(x軸上で)データポイントを特定することです。

XYChart.getSeriesAndPointForScreenCoordinate()ユーザーが線に直接触れる必要があることを除いて、ある種の作業ですが、データポイントのx軸の垂直方向のどこにでも触れることができる必要があります。

チャートスペースをスクリーンスペースに(またはその逆に)変換するだけの問題だと思いますが、Javadocでx位置のみをとるメソッドは見たことがありません。それらはすべてxとyの両方を必要とし、yがデータポイントと一致しない場合、何も返されません。

何か案は?

更新

ダンの知恵を考慮に入れると、toScreenPoint()次のように、メソッドを使用して、特定の画面のx位置の「チャートスペース」x位置を取得できます。

double[] chartPoint = chart.toScreenPoint(new double[] {event.getX(), event.getY()}, 2);
// double[0] == 4935.436905570652

ただし、現在の問題は、この座標を取得して、それに最も近いデータポイントを見つけることです。特定のXYSeriesインデックス/データポイントの「チャートスペース」のx位置を取得する方法があれば、自分で最も近いデータポイントを手動で検索できます。

// Build a list of the data points' chart space x-positions
double[] dataPointPositions = new double[temps.getItemCount()];
for(int index = 0; index < dataPointPositions.length; index++)
{
    dataPointPositions[index] = getXPositionForIndex(index, scale);
}

// (Go thru the list of data point positions, comparing them to the
// value taken from toScreenPoint() to find which one is closest.)

では、百万ドルの問題は、getXPositionForIndex()すでにACEにあるメソッドがあるのか​​、それとも既存のメソッドを使用してメソッドを作成する方法があるのか​​ということです。このメソッドは、XYSeriesデータポイントのインデックス(および場合によってはスケール)を取得し、そのデータポイントの「チャートスペース」のx位置を返します。これは私が立ち往生しているところです。

全体的なアイデアは、画面に触れて、ユーザーが最も近くに触れた10個の(この場合は)データポイントのどれかを見つけることです。

アップデート2

toRealPoint()が返されるかを確認するためにコードを更新しました。これが私のOnTouchListener; ご覧のとおり、取得内容を確認するために、いくつかの異なる値を出力しています。

@Override
public boolean onTouch(View view, MotionEvent event)
{
    Log.i(TAG, "onTouch()");
    Log.i(TAG, "event.x = " + event.getX() + ", event.y = " + event.getY());

    double[] screenPoints = chart.toScreenPoint(new double[] {event.getX(), event.getY()}, 0);
    Log.i(TAG, "Screen points: " + event.getX() + " = " + screenPoints[0] + ", " + event.getY() + " = " + screenPoints[1]);

    double[] realPoints1 = chart.toRealPoint(event.getX(), event.getY());
    Log.i(TAG, "Real points #1: " + event.getX() + " = " + realPoints1[0] + ", " + event.getY() + " = " + realPoints1[1]);

    double[] realPoints2 = chart.toRealPoint((float)screenPoints[0], (float)screenPoints[1]);
    Log.i(TAG, "Real points #2: " + screenPoints[0] + " = " + realPoints2[0] + ", " + screenPoints[1] + " = " + realPoints2[1]);

    return true;
}

残念ながら、私が返す数字は有望ではありません。

03-27 17:10:18.277: I/MainActivity(1149): onTouch()
03-27 17:10:18.277: I/MainActivity(1149): event.x = 98.19905, event.y = 259.41077
03-27 17:10:18.277: I/MainActivity(1149): Screen points: 98.19905 = 2049.3714971127715, 259.41077 = -Infinity
03-27 17:10:18.287: I/MainActivity(1149): Real points #1: 98.19905 = -Infinity, 259.41077 = 44.807568573847
03-27 17:10:18.297: I/MainActivity(1149): Real points #2: 2049.3714971127715 = -Infinity, -Infinity = Infinity

を使用して画面ポイントを実際のポイントに変換しようとすると、toRealPoint()常に-Infinityx位置が表示されます(これは私が本当に気にかけている唯一の位置です)。MotionEvent「生の」スクリーンポイント(から)または「変換された」スクリーンポイント(から取得)を渡すことになっているのかわからなかったのでtoScreenPoint()、両方で試して、何が出力されるかを確認しました。

私は完全に間違ったことをしていますか?そうでない場合、何かアイデアはありますか?

アップデート3

私たち(というか...)は、このように考えすぎていたのではないかと思います。によって提供されるポイントは、MotionEvent実際には翻訳する必要はありません。それが提供する座標は、すでに正しい種類の「画面スペース」です。変換する必要があるのは、データポイントの座標ですそれらは「チャートスペース」にあり、「スクリーンスペース」と比較するには、このように翻訳する必要があります。

次のコードを検討してください。

@Override
public boolean onTouch(View view, MotionEvent event)
{
    Log.i(TAG, "onTouch()");
    Log.i(TAG, "event.x = " + event.getX() + ", event.y = " + event.getY());

    for(int i = 0; i < tempSeries.getItemCount(); i++)
    {
        double x = tempSeries.getX(i);
        double y = tempSeries.getY(i);
        double[] screenPoint = chart.toScreenPoint(new double[] { x, y }, 0);

        Log.i(TAG, x + "," + y + " = " + screenPoint[0] + "," + screenPoint[1]);
    }

    return true;
}

ユーザーが画面に触れると、ここで行っているのはMotionEvent座標を出力することだけです。次に、のすべてのデータポイントをループしますXYSeries。生のポイントを印刷します(合計24個のデータポイントがあるため、0.0から23.0の範囲になります)。また、この方法を使用して、翻訳された「画面スペース」ポイントを印刷しますtoScreenPoint()。これにより、MotionEvent座標をデータポイントの座標と比較できます。

このコードからの長い冗長な出力はそれほど重要ではないので、わざわざ投稿することはしません。重要なのは、「午後8時」のx軸(内部データポイント値が20 [12 + 8 = 20])の周りのどこかで画面に垂直に触れると、MotionEvent受信した座標から次のことがOnTouchListenerわかります。 x位置420.0(+/- 20程度)付近で触れました。ここで、変換されたすべての「screenPoint」値を調べると、約420.0の「午後8時」の値が見つかります。

MotionEventつまり、ユーザーのタッチをデータポイントのx位置の値に変換するには、 x位置を変換されたデータポイントのx位置と比較するだけですtoScreenPoint()。はtoScreenPoint()、データポイントのx位置を、使用するのと同じ座標系MotionEvent(「画面スペース」など)に変換します。そこから、ユーザーがタッチしたときにどのデータポイントに最も近いかを把握することは、変換されたデータポイントのx位置をループし、x位置と比較するという些細なことですMotionEvent。:)

4

1 に答える 1

3

クラスには次のXYChartようなメソッドがあります。

public double[] toScreenPoint(double[] realPoint, int scale)

GraphicalViewただし、これを使用するには、インスタンスの作成に使用された可能性のある方法を放棄する必要があります。

たとえば、これは次のとおりです。

GraphicalView view = ChartFactory.getLineChartView(context, dataset, renderer);

これになります:

XYChart chart = new LineChart(dataset, renderer);
GraphicalView view = new GraphicalView(context, chart);

これを行うことの利点は、chartインスタンスへの参照があるため、前述のメソッドを呼び出すことができることです。

更新:更新された質問は、スクリーンポイントを実際のポイントに変換するための逆の方法を探していると思います。このメソッドは次の場所で使用できますXYChart

public double[] toRealPoint(float screenX, float screenY, int scale)
于 2013-03-27T09:42:54.777 に答える