1

I have a 6300 * 5 array with:

  • Columns 1,2 = CIE data
  • Columns 3,4,5 = S R G B

How should I Draw this in MsChart?

enter image description here

theAlse
  • 5,577
  • 11
  • 68
  • 110
kamran amingalvani
  • 111
  • 1
  • 1
  • 10

1 Answers1

1

You have several options:

  • Add DataPoints with Markers in the respective Colors
  • Add Annotations
  • Use one of the xxxPaint events

With only 6500 points you can't really fill the area by setting single pixels. So you better use a FillElipse call for each point.

If you use the Pre- or PostPaint event you will need to use the AxisX/Y methods ValueToPixelPosition for calculating the pixel coordinates from the CIE values.

In any case you set the Minimum and Maximum for both Axes.

Also you will need to calculate either the Markers' or the Annotations' or the ellipses' size from the chart's ClientSize to avoid ugly gaps in the colored area.

If you want to use DataPoints set the ChartType = Point and use this function for each of your data:

DataPoint Cie2DataPoint(float x, float y, float r, float g, float b)
{
    var dp = new DataPoint(x, y);
    dp.Color = Color.FromArgb((int)(256 * r), (int)(256 * g),(int)(256 * b));
    dp.MarkerColor = dp.Color;
    return dp;
}

Here are examples of helper function:

int MarkerSize(Chart chart, int count)
{
    return Math.Max(chart.ClientSize.Width, chart.ClientSize.Height )/ count + 1
}

void Rescale(Chart chart)
{
    Series s = chart3.Series[0];
    s.MarkerSize = MarkerSize(chart3, (int)Math.Sqrt(s.Points.Count));
}

The former takes an estimate of how many plot points you expect per axis; you may need to experiment a little. The next one assumes the points are actually filling a square; also that you only have one ChartArea.

This should also be modified for your data!

We need to rescale the sizes when the Chart is resized:

private void chart3_Resize(object sender, EventArgs e)
{
    Rescale (sender as Chart);
}

Here is an example of setting it up with a calculated set of data. You should loop over your list of data instead..:

Series s = chart3.Series[0];
s.ChartType = SeriesChartType.Point;
s.MarkerSize = 3;
for (int x = 0; x < 100; x++)
   for (int y = 0; y < 100; y++)
   {
        s.Points.Add(Cie2DataPoint(x/100f, y/100f, x/100f, y/100f, (x+y)/200f));
   }

ChartArea ca = chart3.ChartAreas[0];
ca.AxisX.Minimum = 0;
ca.AxisY.Minimum = 0;
ca.AxisX.Maximum = 1;
ca.AxisY.Maximum = 1;
ca.AxisX.Interval = 0.1f;
ca.AxisY.Interval = 0.1f;
ca.AxisX.LabelStyle.Format = "0.00";
ca.AxisY.LabelStyle.Format = "0.00";

Rescale(chart3);

Result:

enter image description here

After grabbing ~6k colors from a CIE color chart the result looks rather grainy but basically correct:

enter image description here

Note that you probably need to allow for the reversed y-axis somehow; I simply subtracted my y-values from 0.9f. Use your own numbers!

TaW
  • 53,122
  • 8
  • 69
  • 111
  • thank you a lot , very helpful . but I have a problem my point can't fill the areas,how I fill? – kamran amingalvani Feb 08 '17 at 10:57
  • Well valid they may be, but maybe a little incomplete? There seem to be no data for the pink portion, nor for clear yellows? And they also seem to be somewhat unevenly spread.. Where do you get them from? Can I access them to play with them? – TaW Feb 11 '17 at 10:24
  • One way to fill in sparse areas would be to give up on DataPoints and Markers and go for Drawing with a LinearGradientBrush. But this really somewhat defies the idea of representing CIE color space as it will create color mixes in a somewhat linear way. And getting it to actually fille the area is also rather tricky. See [here for an example](http://stackoverflow.com/questions/30339553/fill-panel-with-gradient-in-three-colors/30341521?s=3|0.5582#30341521) that fills a square with 4 interpolated colors.. – TaW Feb 11 '17 at 10:45
  • The above link cold be expanded to fill a polygon, but having suitable data and knowing how they are layed out is still a prerequisite. – TaW Feb 11 '17 at 14:57