Hi,
I have been attemptong to draw a line (in 3D) across a surface plot using the MoveTo3D and LineTo3D functions. Intuitively, I tried using the CalcXPOsValue and CalcYPosValue to obtain the start and end positions for x and y but I see not equivalent for the z value. I winder if there is a simpler way to achieve this or whether I am missing something?
Drawing a line in 3D across a Surface Plot
-
- Newbie
- Posts: 36
- Joined: Wed Aug 24, 2016 12:00 am
Re: Drawing a line in 3D across a Surface Plot
Hello,
You could use the TSurfaceSeries CalcXPos/CalcYPos/CalcZPos functions. Ie:
You could use the TSurfaceSeries CalcXPos/CalcYPos/CalcZPos functions. Ie:
Code: Select all
uses TeeSurfa, TeeTools, TeCanvas;
procedure TForm1.FormCreate(Sender: TObject);
begin
Chart1.Chart3DPercent:=100;
Chart1.Aspect.Orthogonal:=False;
Chart1.Aspect.Zoom:=80;
Chart1.Legend.Visible:=False;
Chart1.AddSeries(TSurfaceSeries).FillSampleValues(10);
Chart1.Tools.Add(TRotateTool);
end;
procedure TForm1.Chart1AfterDraw(Sender: TObject);
function Calc3DPos(ValueIndex: Integer; ASeries: TCustom3DSeries): TPoint3D;
begin
with ASeries do
result:=Point3D(CalcXPos(ValueIndex), CalcYPos(ValueIndex), CalcZPos(ValueIndex));
end;
begin
with Chart1.Canvas do
begin
Pen.Color:=clRed;
MoveTo3D(Calc3DPos(2, Chart1[0] as TSurfaceSeries));
LineTo3D(Calc3DPos(45, Chart1[0] as TSurfaceSeries));
end;
end;
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |
-
- Newbie
- Posts: 36
- Joined: Wed Aug 24, 2016 12:00 am
Re: Drawing a line in 3D across a Surface Plot
Code: Select all
procedure TKPWSurfaceForm.DrawArbitraryLine;
function Calc3DPos(valueIndex: Integer): TPoint3D;
var
xVal, zVal, yVal: Double;
xCo, yCo, zCo: Integer;
begin
xVal := arbitraryLine.XValue[ValueIndex];
xCo := Series1.CalcXSizeValue(xVal);
zVal := arbitraryLine.ZValue[ValueIndex];
zCo := Series1.CalcPosValue(zVal);
yVal := arbitraryLine.YValue[ValueIndex];
yCo := Series1.CalcYPosValue(yVal);
Memo1.Lines.Add(Format('%d %d %d',[xCo,zCo,yCo]));
with Series1 do
Result := Point3D(xCo, zCo, yCo);
end;
var
i: Integer;
pointA, pointB: TPoint3D;
begin
PopulateArbitraryLine;
if arbitraryLine.Count > 1 then
with MainChart.Canvas do
begin
Pen.Color := RGB(51,255,51);
Pen.Width := 5;
for i := 0 to arbitraryLine.Count-2 do // don't connect the final point to the first
begin
Memo1.Lines.Add('From');
pointA := Calc3DPos(i);
Memo1.Lines.Add('To');
pointB := Calc3DPos(i+1);
MoveTo3D(pointA);
LineTo3D(pointB);
end;
end;
end;
Re: Drawing a line in 3D across a Surface Plot
Hello,
First of all note in your code I see some issues:
- You are calling CalcXSizeValue that gives the distance in pixels from the given axis value to the axis value 0.
- You are getting the XValue/YValue/ZValue of the given ValueIndex and then converting it to pixels using the CalcPosValue and CalcYPosValue. That's correct but you can just use CalcXPos/CalcYPos/CalcZPos to get the pixel coordinates from a ValueIndex.
- You seem to be creating the Point3D giving the parameters in the wrong order: It expects x, y and z and you are giving x, z and y.
If you only want to highlight a part of your TSurfaceSeries you could just use a TPoint3DSeries. Ie:
If you want to draw a line that isn't following consecutive points of your TSurfaceSeries, then you should draw the line manually as you were doing. Correcting the issues at the top of this post this way will probably work better.
If you still find problems with it, please try to arrange a simple example project we can run as-is to reproduce the situation here.
First of all note in your code I see some issues:
- You are calling CalcXSizeValue that gives the distance in pixels from the given axis value to the axis value 0.
- You are getting the XValue/YValue/ZValue of the given ValueIndex and then converting it to pixels using the CalcPosValue and CalcYPosValue. That's correct but you can just use CalcXPos/CalcYPos/CalcZPos to get the pixel coordinates from a ValueIndex.
- You seem to be creating the Point3D giving the parameters in the wrong order: It expects x, y and z and you are giving x, z and y.
If you only want to highlight a part of your TSurfaceSeries you could just use a TPoint3DSeries. Ie:
Code: Select all
var
surfaceSeries: TSurfaceSeries;
arbitraryLine: TPoint3DSeries;
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
Chart1.Chart3DPercent:=100;
Chart1.Aspect.Zoom:=80;
Chart1.Aspect.Orthogonal:=False;
Chart1.Legend.Hide;
surfaceSeries:=Chart1.AddSeries(TSurfaceSeries) as TSurfaceSeries;
surfaceSeries.FillSampleValues;
arbitraryLine:=Chart1.AddSeries(TPoint3DSeries) as TPoint3DSeries;
arbitraryLine.Pointer.Visible:=False;
arbitraryLine.Pen.Color:=RGB(51,255,51);
arbitraryLine.Pen.Width:=5;
for i:=42 to 47 do
arbitraryLine.AddXYZ(surfaceSeries.XValue[i], surfaceSeries.YValue[i], surfaceSeries.ZValue[i])
end;
If you still find problems with it, please try to arrange a simple example project we can run as-is to reproduce the situation here.
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |