Getting pixel values from axis label values
Getting pixel values from axis label values
I am trying to save the coordinates of a polygon that I marked on an image
displayed on a TColorGrid so that I can redraw the polygon at a later time.
My users save the polygon vertex values, and at a later date, draw a new image
using a different target and want to redraw the saved polygon.
Below is some example code that I use...
//
// This is the way I put data into the TColorGridSeries. My image data is
// stored in a 2D array of doubles called DblImageData. Note that IrrGrid is
// NOT defined because this code is still VERY slow.
//
for i := 0 to High(DblImageData) do
for j := 0 to High(DblImageData[0]) do
begin
{$ifndef IrrGrid}
// NOTE:
// We are adding 1 to the "X" and "Z" parameters as a work around for a bug
// steema has in their code that is suppose to be fixed in the next release.
// Setting IrregularGrid := True cause images to update REALLY slowly!
(Chart1.Series[SIndex] as TColorGridSeries).AddXYZ(i+1, DblImageData[i,j], j+1);
{$else}
// The axis here is much nicer, but redrawing the image is very slow when
// resizing.
(Chart1.Series[SIndex] as TColorGridSeries).AddXYZ(xScaleOff+i*xScaleMul,
DblImageData[i,j], zScaleOff+j*zScaleMul);
{$endif}
end;
//
// This is the way I fill in the Axis labels when IrregulatGrid is set to false
// which it is in my application.
//
{$ifndef IrrGrid}
// Fill in labels for the X axis.
for i := 0 to High(DblImageData) do
begin
x := i * xScaleMul + xScaleOff;
if (i mod (Length(DblImageData) Div 10) = 0) then
Chart1.Axes.Bottom.Items.add(i,Format('%-.2f',[x]));
end;
// Fill in labels for the Y axis.
for j := 0 to High(DblImageData[0]) do
begin
x := j * zScaleMul + zScaleOff;
if (j mod (Length(DblImageData) Div 10) = 0) then
Chart1.Axes.Left.Items.add(j,Format('%-.2f',[x]));
end;
{$Endif}
//
// I then draw a polygon on the image by getting mouse clicks and saving the
// axis values.
//
// So in procedure TPlotForm.Chart1MouseDown, I get the axis values of points
// clicked on the screen to draw a polygon. I save these points so that later I
// can redraw the polygon on another image with a different zoom and different
// screen size.
//
// NOTE: This is only a code snippet, it is not complete. Unessary application
// specific code and initialization was removed to simplify this example.
//
procedure TPlotForm.Chart1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
fIER_Array[High(fIER_Array)].X := X;
fIER_Array[High(fIER_Array)].Y := Y;
// Add the first vertex to the end of the list so we can close the polygon
// when we draw it
SetLength(fIER_Array, Length(fIER_Array)+1);
fIER_Array[High(fIER_Array)].X := fIER_Array[0].X;
fIER_Array[High(fIER_Array)].Y := fIER_Array[0].Y;
// Save polygon if there is more than 2 points in it.
if Length(fIER_Array) > 2 then
begin
// Draw the polygon.
Chart1.Canvas.Pen.Width := 1;
Chart1.Canvas.Polyline(fIER_Array);
// Save the current polygon in the IER shape list.
SetLength(fIERRecList, Length(fIERRecList)+1);
j := High(fIERRecList);
i := Length(fIER_Array);
// Pixel locations of each vertex
SetLength(fIERRecList[j].Point_List, i);
SetLength(fIERRecList[j].X_Values, i); // X axis values
SetLength(fIERRecList[j].Y_Values, i); // Y axis values
for i := 0 to High(fIER_Array) do
begin
// Save the X and Y pixel positions or the vertex points. This is
// really useless because the images sizez will be different!!
fIERRecList[j].Point_List := fIER_Array;
// Get the index of the point clicked.
k := Chart1.Series[0].Clicked(fIER_Array.X,fIER_Array.Y);
// Save the value of the axis label of the point clicked.
fIERRecList[j].X_Values := (k div (Chart1.Series[0] as TColorGridSeries).NumZValues) *
xScaleMul + xScaleOff;
fIERRecList[j].Y_Values := (k mod (Chart1.Series[0] as TColorGridSeries).NumZValues) *
zScaleMul + zScaleOff ;
end;
end;
end;
Now that I have the axis label values of the points in the polygon, how can I
go backwards to the pixel locations on a new image made sometime inthe future?
For example, if I collect data on a different target and display the image, I
want to redraw the polygon on the new target at the same x/y positions.
How do I get the pixel locations from the fIERRecList[j].X_Value and
fIERRecList[j].Y_Value arrays that I saved earlier?
Is there a better way to do this with Irregular grid set to False?
displayed on a TColorGrid so that I can redraw the polygon at a later time.
My users save the polygon vertex values, and at a later date, draw a new image
using a different target and want to redraw the saved polygon.
Below is some example code that I use...
//
// This is the way I put data into the TColorGridSeries. My image data is
// stored in a 2D array of doubles called DblImageData. Note that IrrGrid is
// NOT defined because this code is still VERY slow.
//
for i := 0 to High(DblImageData) do
for j := 0 to High(DblImageData[0]) do
begin
{$ifndef IrrGrid}
// NOTE:
// We are adding 1 to the "X" and "Z" parameters as a work around for a bug
// steema has in their code that is suppose to be fixed in the next release.
// Setting IrregularGrid := True cause images to update REALLY slowly!
(Chart1.Series[SIndex] as TColorGridSeries).AddXYZ(i+1, DblImageData[i,j], j+1);
{$else}
// The axis here is much nicer, but redrawing the image is very slow when
// resizing.
(Chart1.Series[SIndex] as TColorGridSeries).AddXYZ(xScaleOff+i*xScaleMul,
DblImageData[i,j], zScaleOff+j*zScaleMul);
{$endif}
end;
//
// This is the way I fill in the Axis labels when IrregulatGrid is set to false
// which it is in my application.
//
{$ifndef IrrGrid}
// Fill in labels for the X axis.
for i := 0 to High(DblImageData) do
begin
x := i * xScaleMul + xScaleOff;
if (i mod (Length(DblImageData) Div 10) = 0) then
Chart1.Axes.Bottom.Items.add(i,Format('%-.2f',[x]));
end;
// Fill in labels for the Y axis.
for j := 0 to High(DblImageData[0]) do
begin
x := j * zScaleMul + zScaleOff;
if (j mod (Length(DblImageData) Div 10) = 0) then
Chart1.Axes.Left.Items.add(j,Format('%-.2f',[x]));
end;
{$Endif}
//
// I then draw a polygon on the image by getting mouse clicks and saving the
// axis values.
//
// So in procedure TPlotForm.Chart1MouseDown, I get the axis values of points
// clicked on the screen to draw a polygon. I save these points so that later I
// can redraw the polygon on another image with a different zoom and different
// screen size.
//
// NOTE: This is only a code snippet, it is not complete. Unessary application
// specific code and initialization was removed to simplify this example.
//
procedure TPlotForm.Chart1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
fIER_Array[High(fIER_Array)].X := X;
fIER_Array[High(fIER_Array)].Y := Y;
// Add the first vertex to the end of the list so we can close the polygon
// when we draw it
SetLength(fIER_Array, Length(fIER_Array)+1);
fIER_Array[High(fIER_Array)].X := fIER_Array[0].X;
fIER_Array[High(fIER_Array)].Y := fIER_Array[0].Y;
// Save polygon if there is more than 2 points in it.
if Length(fIER_Array) > 2 then
begin
// Draw the polygon.
Chart1.Canvas.Pen.Width := 1;
Chart1.Canvas.Polyline(fIER_Array);
// Save the current polygon in the IER shape list.
SetLength(fIERRecList, Length(fIERRecList)+1);
j := High(fIERRecList);
i := Length(fIER_Array);
// Pixel locations of each vertex
SetLength(fIERRecList[j].Point_List, i);
SetLength(fIERRecList[j].X_Values, i); // X axis values
SetLength(fIERRecList[j].Y_Values, i); // Y axis values
for i := 0 to High(fIER_Array) do
begin
// Save the X and Y pixel positions or the vertex points. This is
// really useless because the images sizez will be different!!
fIERRecList[j].Point_List := fIER_Array;
// Get the index of the point clicked.
k := Chart1.Series[0].Clicked(fIER_Array.X,fIER_Array.Y);
// Save the value of the axis label of the point clicked.
fIERRecList[j].X_Values := (k div (Chart1.Series[0] as TColorGridSeries).NumZValues) *
xScaleMul + xScaleOff;
fIERRecList[j].Y_Values := (k mod (Chart1.Series[0] as TColorGridSeries).NumZValues) *
zScaleMul + zScaleOff ;
end;
end;
end;
Now that I have the axis label values of the points in the polygon, how can I
go backwards to the pixel locations on a new image made sometime inthe future?
For example, if I collect data on a different target and display the image, I
want to redraw the polygon on the new target at the same x/y positions.
How do I get the pixel locations from the fIERRecList[j].X_Value and
fIERRecList[j].Y_Value arrays that I saved earlier?
Is there a better way to do this with Irregular grid set to False?
-
- Site Admin
- Posts: 14730
- Joined: Mon Jun 09, 2003 4:00 am
- Location: Banyoles, Catalonia
- Contact:
Hi dpatch,
You can use CalcPosValue method for that:How do I get the pixel locations from the fIERRecList[j].X_Value and
fIERRecList[j].Y_Value arrays that I saved earlier?
Code: Select all
XPos:=Chart1.Axes.Bottom.CalcPosValue(fIERRecList[j].X_Value);
YPos:=Chart1.Axes.Left.CalcPosValue(fIERRecList[j].Y_Value);
Not that I can think of. It is recommended to use IrregularGrid=false whenever possible as it makes series much more eficient.Is there a better way to do this with Irregular grid set to False?
Best Regards,
Narcís Calvet / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
-
- Site Admin
- Posts: 14730
- Joined: Mon Jun 09, 2003 4:00 am
- Location: Banyoles, Catalonia
- Contact:
Hi dpatch,
No, CalcPosValue takes a double value for me and returns an integer. In a similar way, you can use CalcXPosValue and CalcYPosValue methods:
No, CalcPosValue takes a double value for me and returns an integer. In a similar way, you can use CalcXPosValue and CalcYPosValue methods:
Hope this helps!XPos:=Chart1.Axes.Bottom.CalcXPosValue(fIERRecList[j].X_Value);
YPos:=Chart1.Axes.Left.CalcYPosValue(fIERRecList[j].Y_Value);
Best Regards,
Narcís Calvet / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
Yes, I see that you are correct. I was looking at the series1.CalcPosValue example in your help file.
When I call the example code you supplied, I did not get the right answer. I wonder if I did not save the axis value in the array X_Value correctly. Could you look at the end of the example code where I calculated this value and tell me if it is wrong?
X and Y are gotten in the OnMouseDown event.
// Get the index of the point clicked.
k := Chart1.Series[0].Clicked(X, Y);
// Save the value of the axis label of the point clicked.
fIERRecList[j].X_Values := (k div (Chart1.Series[0] as TColorGridSeries).NumZValues) * xScaleMul + xScaleOff;
fIERRecList[j].Y_Values := (k mod (Chart1.Series[0] as TColorGridSeries).NumZValues) * zScaleMul + zScaleOff ;
Thank you.
When I call the example code you supplied, I did not get the right answer. I wonder if I did not save the axis value in the array X_Value correctly. Could you look at the end of the example code where I calculated this value and tell me if it is wrong?
X and Y are gotten in the OnMouseDown event.
// Get the index of the point clicked.
k := Chart1.Series[0].Clicked(X, Y);
// Save the value of the axis label of the point clicked.
fIERRecList[j].X_Values := (k div (Chart1.Series[0] as TColorGridSeries).NumZValues) * xScaleMul + xScaleOff;
fIERRecList[j].Y_Values := (k mod (Chart1.Series[0] as TColorGridSeries).NumZValues) * zScaleMul + zScaleOff ;
Thank you.
-
- Site Admin
- Posts: 14730
- Joined: Mon Jun 09, 2003 4:00 am
- Location: Banyoles, Catalonia
- Contact:
Hi dpatch,
You could try something easier:
You could try something easier:
Code: Select all
fIERRecList[j].X_Values[i] := Chart1[0].XValue[k];
fIERRecList[j].Y_Values[i] := Chart1[0].YValue[k];
Best Regards,
Narcís Calvet / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
There are 2 problems with the solution that you recommend.
The first is that your solution returns the "integer" index of the X/Y pixel locations on the original axis when the Mouse Down event was generated. This index will not longer be valid on the next image that the uses generages...especially if it is at a different zoom. I also do not believe that calculating the axis value works with this index.
Secondly, I am not trying to get the index of the chart, I am trying to get the floating point value that I put into the axis label for that index. If you look carefully at my code segment below, you will see that I have a for loop that generates a floating point axis label value starting at an offset and multiplying by a scaling factor.
Is there a way to get directly to the floating point value of the axis from the X/Y coordinates in the Mouse Down event? Also, I need to get back from the floating point to the X/Y coordinate (or the pixel location) to be able to redraw the polygon an o different plot.
If this explanation is not clear, please make me explain myself better. I really need to be able to do this. I am afraid that this is not working because I am using IregularGrid := False.
The first is that your solution returns the "integer" index of the X/Y pixel locations on the original axis when the Mouse Down event was generated. This index will not longer be valid on the next image that the uses generages...especially if it is at a different zoom. I also do not believe that calculating the axis value works with this index.
Secondly, I am not trying to get the index of the chart, I am trying to get the floating point value that I put into the axis label for that index. If you look carefully at my code segment below, you will see that I have a for loop that generates a floating point axis label value starting at an offset and multiplying by a scaling factor.
Is there a way to get directly to the floating point value of the axis from the X/Y coordinates in the Mouse Down event? Also, I need to get back from the floating point to the X/Y coordinate (or the pixel location) to be able to redraw the polygon an o different plot.
If this explanation is not clear, please make me explain myself better. I really need to be able to do this. I am afraid that this is not working because I am using IregularGrid := False.
-
- Site Admin
- Posts: 14730
- Joined: Mon Jun 09, 2003 4:00 am
- Location: Banyoles, Catalonia
- Contact:
Hi dpatch,
Thanks for the information.
Thanks for the information.
Yes, in that case you can use CalcPosPoint method:Is there a way to get directly to the floating point value of the axis from the X/Y coordinates in the Mouse Down event?
Code: Select all
XVal:=Chart1.Axes.Bottom.CalcPosPoint(X);
YVal:=Chart1.Axes.Left.CalcPosPoint(Y);
For the inverse operation you can use this:Also, I need to get back from the floating point to the X/Y coordinate (or the pixel location) to be able to redraw the polygon an o different plot.
Code: Select all
X:=Chart1.Axes.Bottom.CalcXPosValue(XVal);
Y:=Chart1.Axes.Left.CalcYPosValue(YVal);
Best Regards,
Narcís Calvet / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
OK, maybe I replied too fast...
The methods CalcPosPoint and CalcXPosValue do seem to work in that they allow me to redraw polygons in absoultuely the correct positions on different images. However, if you look at the axis positions values CalcPosPoint returns, it does not match the value on the x or y axis. Meaning, I have an axis scale that goes from -4.00 to +4.00 and CalcXPoint returns a number like 48.35475.
It's good that I can redraw the polygons, but I can't display the vertex values because they still are not correct.
Any thoughts on what I might be doing wrong?
The methods CalcPosPoint and CalcXPosValue do seem to work in that they allow me to redraw polygons in absoultuely the correct positions on different images. However, if you look at the axis positions values CalcPosPoint returns, it does not match the value on the x or y axis. Meaning, I have an axis scale that goes from -4.00 to +4.00 and CalcXPoint returns a number like 48.35475.
It's good that I can redraw the polygons, but I can't display the vertex values because they still are not correct.
Any thoughts on what I might be doing wrong?
-
- Site Admin
- Posts: 14730
- Joined: Mon Jun 09, 2003 4:00 am
- Location: Banyoles, Catalonia
- Contact:
Hi dpatch,
Could you please send us a simple example project we can run "as-is" to reproduce the problem here?
You can either post your files at news://www.steema.net/steema.public.attachments newsgroup or at our upload page.
Thanks in advance.
Could you please send us a simple example project we can run "as-is" to reproduce the problem here?
You can either post your files at news://www.steema.net/steema.public.attachments newsgroup or at our upload page.
Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
Yes, I will try to, but it is quite a lot of code...
It seems that the disconnect is between the values I load into the axis using:
Chart1.Series[SIndex].AddXYZ(i+1, DblImageData[i,j], j+1)
and the values I load into the x axis labels using:
Chart1.Axes.Bottom.Items.add(i,Format('%-.2f',[x]))
The code solution you gave me works, but it is calculating positions based on the values in chart.XValues array, not the values in the Chart.Axes label.
Is there a way to tie back to the values displayed onthe label? If so, I will put together some sample code and get it to you...
Thanks
It seems that the disconnect is between the values I load into the axis using:
Chart1.Series[SIndex].AddXYZ(i+1, DblImageData[i,j], j+1)
and the values I load into the x axis labels using:
Chart1.Axes.Bottom.Items.add(i,Format('%-.2f',[x]))
The code solution you gave me works, but it is calculating positions based on the values in chart.XValues array, not the values in the Chart.Axes label.
Is there a way to tie back to the values displayed onthe label? If so, I will put together some sample code and get it to you...
Thanks
-
- Site Admin
- Posts: 14730
- Joined: Mon Jun 09, 2003 4:00 am
- Location: Banyoles, Catalonia
- Contact:
Hi dpatch,
I might be not understanding what you are trying to do. That's why a little code example would help.
Anyway, you could try using series' XScreenToValue and YScreenToValue which gives an axis value from a screen coordinate.
I might be not understanding what you are trying to do. That's why a little code example would help.
Anyway, you could try using series' XScreenToValue and YScreenToValue which gives an axis value from a screen coordinate.
Best Regards,
Narcís Calvet / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |