2016-07-19 4 views
0

У меня есть полярная диаграмма с несколькими сериями. Я хочу иметь функциональность, чтобы щелкнуть по одному из datapoints в любой серии и выполнить что-то. Я попытался использовать HitTest, и он работает в одной серии. Проблема в том, что я использовал на диаграмме с несколькими рядами, а иногда, когда я нажимаю на datapoint, она возвращает другую точку. Пожалуйста помоги.hittest в полярной схеме с несколькими сериями

Это фрагмент, который я использовал.

HitTestResult result = chart1.HitTest(e.X, e.Y, ChartElementType.DataPoint); 
if (result.ChartElementType == ChartElementType.DataPoint) 
{ 
    var xVal = result.Series.Points[result.PointIndex].XValue; 
    var yVal = result.Series.Points[result.PointIndex].YValues; 
    result.Series.Points[result.PointIndex].MarkerColor = Color.Black; 
} 

обновление:

Спасибо вам так много для подшипников со мной. Во всяком случае, это код, включающий то, что вы предложили.

DataPoint dpCurrent = null; 
    int normalMarkerSize = 10; 
    int largeMarkerSize = 15; 

    private void chart1_MouseClick(object sender, MouseEventArgs e) 
    { 
     HitTestResult result = chart1.HitTest(e.X, e.Y, ChartElementType.DataPoint); 
     if (result.ChartElementType == ChartElementType.DataPoint) 
     { 
      dpCurrent = result.Series.Points[result.PointIndex]; 
      if (distance(PolarValueToPixelPosition(dpCurrent, chart1, result.ChartArea), e.Location) <= 5) 
       result.Series.Points[result.PointIndex].MarkerColor = Color.Black; 
     } 
    } 

Однако я заметил, что значение «фи» в PolarValueToPixelPosition всегда возвращается NaN

+0

Это здесь работает отлично. Как именно вы знаете, что неправильный маркер окрашен? Может быть, точки перекрываются? Вы понимаете, что hittest передает данные не только при нажатии __marker__, но и на __line__; в диаграмме __polar__ сообщается о точке, которая является __closest__! – TaW

+0

Возможно, вы захотите сделать предварительный просмотр точки в mousemove, установив ее цвет на другой цвет, сделав ее более крупной, пока мышь не исчезнет. – TaW

+0

Привет @TaW, спасибо за ответ. На самом деле, моя карта содержит почти тысячу очков. Я просто скрываю линии, поэтому на графике видны только точки. Есть ли способ, чтобы линии были исключены, когда я нажимаю на диаграмму. Мне просто нужны очки. – overmind

ответ

0

Вот два пути решения этой проблемы; никто не может фактически сделать HitTestигнорировать нажав на соединительные линии.

Но они должны быть в порядке, особенно если вы их реализуете.

Первые обеспечивает обратную связь пользователя, чтобы он мог видеть заранее, какой указатель мыши находится над и он собирается нажать:

DataPoint dpCurrent = null; 
int normalMarkerSize = 8; 
int largeMarkerSize = 12; 

private void chart1_MouseMove(object sender, MouseEventArgs e) 
{ 
    HitTestResult hit = chart1.HitTest(e.X, e.Y); 
    if (hit.ChartElementType == ChartElementType.DataPoint) 
    { 
     dpCurrent = hit.Series.Points[hit.PointIndex]; 
     dpCurrent.MarkerSize = largeMarkerSize; 
    } 
    else 
    { 
     if (dpCurrent != null) dpCurrent.MarkerSize = normalMarkerSize; 
     dpCurrent = null; 
    } 

К сожалению HitTest будет еще вызвать DataPoint хит даже если только вы не попали соединительные линии , независимо от того, насколько тонка вы делаете их или какой цвет у них есть ..

решение ..enter два:

Можно написать пользовательский HitTest, вычислив пиксельные координаты DataPoints; это не так просто, как вызывая Axis.ValueToPixelPosition метод, как это предполагает некоторую скромную сумму математики ..:

Теперь перед обработкой удара вы могли бы сделать дополнительную проверку, может быть, как это:

if (distance(PolarValueToPixelPosition(dpCurrent, chart1, 
     hit.ChartArea), e.Location) <= markerRadius) ...//do the hit stuff 

Вот функция преобразования координат:

PointF PolarValueToPixelPosition(DataPoint dp, Chart chart, ChartArea ca) 
{ 
    RectangleF ipp = InnerPlotPositionClientRectangle(chart, ca); 
    double crossing = ca.AxisX.Crossing != double.NaN ? ca.AxisX.Crossing : 0; 

    // for RangeChart change 90 zo 135 ! 
    float phi = (float)(360f/ca.AxisX.Maximum/180f * Math.PI * 
      (dp.XValue - 90 + crossing)); 

    float yMax = (float)ca.AxisY.Maximum; 
    float yMin = (float)ca.AxisY.Minimum; 
    float radius = ipp.Width/2f; 
    float len = (float)(dp.YValues[0] - yMin)/(yMax - yMin); 
    PointF C = new PointF(ipp.X + ipp.Width/2f, ipp.Y + ipp.Height/2f); 

    float xx = (float)(Math.Cos(phi) * radius * len); 
    float yy = (float)(Math.Sin(phi) * radius * len); 
    return new PointF(C.X + xx, C.Y + yy); 
} 

Он использует простую функцию расстояния ..:

float distance(PointF pt1, PointF pt2) 
{ 
    float d = (float)Math.Sqrt((pt1.X - pt2.X) * (pt1.X - pt2.X) 
           + (pt1.Y - pt2.Y) * (pt1.Y - pt2.Y)); 
    return d; 
} 

Кроме двух других полезных функций для расчета размера пикселя InnerPlotPosition, который я использовал в довольно много ответов сейчас ..:

RectangleF ChartAreaClientRectangle(Chart chart, ChartArea CA) 
{ 
    RectangleF CAR = CA.Position.ToRectangleF(); 
    float pw = chart.ClientSize.Width/100f; 
    float ph = chart.ClientSize.Height/100f; 
    return new RectangleF(pw * CAR.X, ph * CAR.Y, pw * CAR.Width, ph * CAR.Height); 
} 

RectangleF InnerPlotPositionClientRectangle(Chart chart, ChartArea CA) 
{ 
    RectangleF IPP = CA.InnerPlotPosition.ToRectangleF(); 
    RectangleF CArp = ChartAreaClientRectangle(chart, CA); 

    float pw = CArp.Width/100f; 
    float ph = CArp.Height/100f; 

    return new RectangleF(CArp.X + pw * IPP.X, CArp.Y + ph * IPP.Y, 
          pw * IPP.Width, ph * IPP.Height); 
} 
+0

Привет, я очень ценю помощь, которую вы мне дали. Но я не уверен, что я следую тому, как использовать написанные вами функции и какова ценность маркера Radius? Спасибо. – overmind

+0

Ну, ваши маркеры имеют размер. Пользовательский hittest должен проверять, находится ли мышь на маркере и не просто на линии. Половина маркеров - это допустимое расстояние от точки данных. Таким образом, вы добавляете тест ('if (distance ..)') к тесту, который у вас уже есть ('if (result.ChartElementType..') ... Продолжайте просить, пока мы его не очистили! – TaW

+0

привет, я ценю ваша помощь. Пример кода обновлен выше, но я всегда получаю значение NaN для phi. Знаете ли вы, что это происходит? спасибо! – overmind

Смежные вопросы