Getting pixel values from axis label values

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Fri Sep 12, 2008 1:48 pm

Hi dpatch,

Yes, we received the files, built your project and could reproduce the problem here but we need some time to investigate what's wrong here. We will get back to you when we have further news.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Marc
Site Admin
Site Admin
Posts: 1214
Joined: Thu Oct 16, 2003 4:00 am
Location: Girona
Contact:

Post by Marc » Wed Sep 17, 2008 4:04 pm

Hello,

The Polygon values returned in your demo project by CalcPosPoint are correct and coincide with the Axes' scales and Chart values.

If you were to disable the lines that populate the Custom Axis Labels you will see that the polygon data correctly reflect Axis data:

Code: Select all

To test comment the lines and run the project:
//Chart1.Axes.Bottom.Items.add ...
and
//Chart1.Axes.Left.Items.add ...
You need to obtain values according to the scale you have used for the Custom Labels. An option would be to create a lookup routine back to your data to translate the Chart values to your custom scale.

Regards,
Marc Meumann
Steema Support

dpatch
Newbie
Newbie
Posts: 53
Joined: Mon Jul 02, 2007 12:00 am

Post by dpatch » Wed Sep 17, 2008 4:49 pm

I want to be sure that I understand exactly what you are saying.

I agree that CalcPosPoint is returning the axis values I put in using the Chart1.Series[index].AddXYZ method. Using that method because I have IrregularGrid set to false, I just increment a counter for the X and Z values. So, CalcPosPoint returns a floating point number between 1 and the number of points in the plot..in this case 128. Is this correct?

So, I think what you are saying, is that there is no direct way to get the a corresponding point on my custom label. I need to write a routine to do this myself. Is this also correct?

It is ok if I have to, actually, I already do this when I generate the custom axis labels. I was just hoping that your routines would return the custom axis value for me. I am afraid that I may run into problems when I start to rotate the polygons in 2D space.

Thanks in advance for your time...

Marc
Site Admin
Site Admin
Posts: 1214
Joined: Thu Oct 16, 2003 4:00 am
Location: Girona
Contact:

Post by Marc » Thu Sep 18, 2008 3:39 pm

Hello,
CalcPosPoint returns a floating point number between 1 and the number of points in the plot..in this case 128. Is this correct?
Not quite correct (I think - if I've followed your text correctly). I see it as follows:CalcPosPoint returns the actual on-Chart value at the x,y pixel location passed to it. In your example that will be anywhere between 0 and 500 on either the Left or Bottom Axes. Comment the label population lines in your example and build a polygon and you will see the values coincide exactly with the default Axis scales.
no direct way to get the a corresponding point on my custom label. I need to write a routine to do this myself. Is this also correct?
Correct. You would need to follow/backstep the steps you use to create the Labels. We couldn't think of a better way when we looked at it though it does the raise a feature request that we've now noted ... for an in-Chart technique to extract the nearest Label index from an x,y location. We'll look to do that for a future version.

Regards,
Marc
Steema Support

dpatch
Newbie
Newbie
Posts: 53
Joined: Mon Jul 02, 2007 12:00 am

Post by dpatch » Thu Sep 18, 2008 3:49 pm

Your last answer is what I suspected.

And, I agree that an "in-chart" solution to calculate the nearest axis Label index (or value) from an x,y point is a necessary function due to the inefficiencies of the chart when IrregularGrid is true. Also, given an axis label value, calculating the nearest x,y point would be the other half of the new feature.

Thanks Marc (and everyone), I appreciate your time.

dpatch
Newbie
Newbie
Posts: 53
Joined: Mon Jul 02, 2007 12:00 am

Post by dpatch » Tue Jan 13, 2009 6:18 pm

Hello, it has bee a while.

I am still unable to translate point values from the axis labels I created to pixel values on the screen so I can re-draw my polygons.

I have posted a simplified example on the upload page link you supplied earlied in this thread. It is called "Image Test 2.zip". There are coments in this example describing exactly what aI am trying to do. Can you please review this file and get back to me? I am really in a jam!

Thanks in advance.

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Wed Jan 14, 2009 11:47 am

Hi dpatch,

I think the problem here is that you are using axis scales values with screen coordinates.

In the Chart1MouseDown method you save polygon points like this:

Code: Select all

      // Save the new vertex
      fVertex_List[High(fVertex_List)].X := X;
      fVertex_List[High(fVertex_List)].Y := Y;
Here X and Y are screen coordinates.

Later on the method you perform a transformation on them to be according to your custom axis labels:

Code: Select all

              fPolygon_List[j].X_Values[i] := Chart1.Axes.Bottom.CalcPosPoint(fVertex_List[i].X) * fxScaleMul + fxScaleOff;
              fPolygon_List[j].Y_Values[i] := Chart1.Axes.Left.CalcPosPoint(fVertex_List[i].Y) * fzScaleMul + fzScaleOff;
I think the error here as you are mixing series/axis values with screen coordinates doing this transformation. Then, at RedrawPolygonsClick method it's quite tricky "undoing" the transformation to get screen coordinates again for plotting the polygons. Those custom labels may be good for your chart visualisation but are a problem for internal calculations.

Having said that, my suggestion is that you try to save polygon points relative to axis values in a floating point structure, something like this:

Code: Select all

      fVertex_List[High(fVertex_List)].X := Chart1.Axes.Bottom.CalcPosPoint(X);
      fVertex_List[High(fVertex_List)].Y := Chart1.Axes.Left.CalcPosPoint(Y);
If possible, don't do any transformation on those values so that in RedrawPolygonsClick method you will just need to retrieve fVertex_List's axes values and convert them back to screen coordinates for plotting the polygons, for example:

Code: Select all

          Vertex_List[j].X := Chart1.Axes.Bottom.CalcXPosValue(Saved_Polygon_List[i].X_Values[j]);
          Vertex_List[j].Y := Chart1.Axes.Left.CalcYPosValue(Saved_Polygon_List[i].Y_Values[j]);
Hope my explanation was clear and helpful for you. Otherwise don't hesitate to let us know.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Wed Jan 14, 2009 12:37 pm

Hi dpatch,

I'd also like to comment that for running your project here I removed RTInumbers objects and related code. My impression was they don't have any effect on the problem discussed here, do they?

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
Image Image Image Image Image Image
Instructions - How to post in this forum

dpatch
Newbie
Newbie
Posts: 53
Joined: Mon Jul 02, 2007 12:00 am

Post by dpatch » Wed Jan 14, 2009 1:49 pm

Thank you for your quick response.

You are correct, RTInumbers do NOT have an impact on this issue. I tried to remove unnecessary code when I cut and pasted from a larger project. I just missed that one.

Your explaination is very clear. I will give it a try and let you know how it goes.

Thanks again!

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Wed Jan 14, 2009 2:04 pm

Hi dpatch,

I've made a quick test implementing what I explained in your project and it works even it needs to be improved.

I just sent you an e-mail with the modified project. RedrawPolygonsClick now draws the polygons but first one is always linked to the left-bottom corner of the chart and in case of mulitple polygons they are also linked.

Hope this helps!
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Wed Jan 14, 2009 2:07 pm

Hi dpatch,

BTW: The project with my modifications also gives a Range check error.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Wed Jan 14, 2009 2:34 pm

Hi dpatch,
BTW: The project with my modifications also gives a Range check error.
Which can be solved using this code:

Code: Select all

          //
          // Convert and the points collected for the polygon to my axis values.
          //
          // NOTE: These are the points that I need to use when re-drawing the
          //       polygons on a new image.
          //
          for i := 0 to High(fAxesVertices_List) do
            begin
              fPolygon_List[j].X_Values[i] := fAxesVertices_List[i].X;
              fPolygon_List[j].Y_Values[i] := fAxesVertices_List[i].Y;

              // These are the points used in procedure RedrawPolygonsClick to
              // re-draw the polygons.
              Saved_Polygon_List[j] := fPolygon_List[j];
            end;
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

dpatch
Newbie
Newbie
Posts: 53
Joined: Mon Jul 02, 2007 12:00 am

Post by dpatch » Wed Jan 14, 2009 3:57 pm

I have recieved your code changes and looked at them. I think maybe I have not made my problem understood.

What I am doing is generating an image of a target and measuring the distance of its features in feet from the center. That is why I need to change the axis values to make zero at the center. Once I have the image, I draw the polygon around the features. I then generate a new image of a different target and take the polygons from the previous image and redraw then on the new image to see if the features have moved.

Since the scale can change, it is important that I save the distance in feet of each vertex, not it's axis position. That is why I applied the transform to the X/Y values. When I redraw the polygons on a new image, it is important that I place each vertex at the same "distance" in feet from the center. They may not be in the same X/Y position on the chart if my axis labels change. In your example, you removed the transform so you did not save the distance, only the axis position.

If you look at my original code, you will see that I performed the transform and saved the distance (or my axis values). My problem is that how do I get a new X/Y for a given an axis value, i.e. 2.5 feet?

In other words, if you look at my image, can you place a polygon on that image if I gave you only values from my axis labels that are in feet?

For example,
point1: x= -4.26, y= -2.66 feet
point2: x= -3.20, y= -2.50 feet
point3: x= -3.25, y= -2.00 feet

See here you do not have the axis positions that you saved in you example, only the distance from the center of the target. How can I get the new axis positions given only values from the axis labels I created using my transform?

If this is not clear, please let me know. I really need to solve this problem. If you want, I can also send you my original example if you did not save it. Also, I can create another one if you are still not clear on my problem.

Thanks so much.

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Thu Jan 15, 2009 12:54 pm

Hi dpatch,

Thanks for the information. Now I understand which is the exact problem here.

In that case I think that a solution might be this:

1. Associating 4 default axes (left, top, right and bottom) to your series.
2. Use left and bottom axes as you already do for plotting the chart.
3. Manually set top and right axes scales. The point here would be being able to calculate each axis minimum and maximum value according to your transformation and assign such values to top and right axes using SetMinMax method. This calculation may be obtained from Series’s MinXValue, MaxXValue, MinYValue and MaxYValue with the transformation factors. For example:

Code: Select all

        Chart1[0].VertAxis:=aBothVertAxis;
        Chart1[0].HorizAxis:=aBothHorizAxis;

        Chart1.Axes.Top.SetMinMax(Chart1[0].MinXValue * fxScaleMul + fxScaleOff,
                                  Chart1[0].MaxXValue * fxScaleMul + fxScaleOff );

        Chart1.Axes.Right.SetMinMax(Chart1[0].MinYValue * fzScaleMul + fzScaleOff,
                                  Chart1[0].MaxYValue * fzScaleMul + fzScaleOff );
4. Use right and top axes values for definning the polygons. This way you wouldn't need the transformation here. It would be just necessary in previous step for calculating top and right axes scales. For example:

Code: Select all

      fAxesVertex_List[High(fAxesVertex_List)].X := Chart1.Axes.Top.CalcPosPoint(X);
      fAxesVertex_List[High(fAxesVertex_List)].Y := Chart1.Axes.Right.CalcPosPoint(Y);
5. Now you should be able to draw polygons again using the right and top axes values you have calculated as I suggested in my previous reply For example:

Code: Select all

          Vertex_List[j].X := Chart1.Axes.Top.CalcXPosValue(Saved_Polygon_List[i].X_Values[j]);
          Vertex_List[j].Y := Chart1.Axes.Right.CalcYPosValue(Saved_Polygon_List[i].Y_Values[j]);
The key with this approach is the transformation calculation in point 3 and doing so every time a new chart is plotted.

I think I implemented this successfully to your project. I'm going to send it now by e-mail.

Is that what you were looking for?
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

dpatch
Newbie
Newbie
Posts: 53
Joined: Mon Jul 02, 2007 12:00 am

Post by dpatch » Thu Jan 15, 2009 4:23 pm

Outstanding!

I dont know why I wasn't able to do what you did with the top and bottom axis. That is all I really need to do with the bottom and left.

I will continue to look at what you sent, but it looks really good.

Thank you very much for your support.

Post Reply