Page 1 of 2

Drawing a line between points

Posted: Mon Oct 06, 2008 5:07 pm
by 9232632
running TChart v7.06 in Borland Builder 6.0

would like to have a "series" that is made up of line segments. tried a simple point series and set the series DrawBetweenPoints property to true. also set Pen and LinePen properties to Visible and clBlack. i use series->addXY to add the points to the series. looking at the graph, i see the points (where they should be), but there's no line between them.

is there an additional property i need to set?
is there a different chart type that i should be using?

Posted: Tue Oct 07, 2008 7:45 am
by narcis
Hi rperkins,

You could try using a line series setting its Pointer to visible, for example:

Code: Select all

  Chart1.View3D:=false;
  Series1.Pointer.Visible:=true;
  Series1.Pen.Style:=psSolid;
Please notice that you can set different pen styles.

If this doesn't help please give us some more details about what you are trying to get exactly.

Thanks in advance.

Posted: Tue Oct 07, 2008 12:54 pm
by 9232632
i had thought about setting the series up as a line series. in my test app, i changed the series from a point series to a line, and was able to see the lines between the points. problem is that i don't have consecutive points, nor do i have the ability to order them.

what i'm looking to do is take a series of points and given a starting point and end point (both of which i know) of a line segment, add them to the series, and, have a line drawn between them. (this may not even be possible in TeeChart, but wanted to try)

the real world situation is for sections of a ship and trying to create a perimeter outline given the points (which are not in ANY order) without knowing anything about the ship section.

imagine a Q-tip. now, slice it in half - lengthwise. the stick part is assumed to be 1 pixel wide. now, in one of the ends, hollow it out, abit - still leaving the stick. stand the Q-tip on end, with the hollowed out part at the top. with the full end down, and at 0,0, begin walking aroung the perimeter. you have to discount the hollow part, or you might think it's part of the perimeter. the goal is to provide a perimeter trace of what's left. (hope this "example" helps illustrate the "problem").

an additional kicker is that the shape can be anything - not just like a Q-tip - it can be more like a traditional ship hull section.

Posted: Tue Oct 07, 2008 2:23 pm
by narcis
Hi rperkins,

Thanks for the information. I'm still not 100% sure about what you are looking for. I imagine I'm loosing something here as English is not my mother tongue.

However, you might be interested in using TeeChart's perimeter function then. You'll find an example at All Features\Functions\Extended\Perimeter Function in the new features demo. A tutorial about TeeChart function's usage is also available. Tutorials and demo can be found at TeeChart's program group.

If that's not what you are looking for I'll ask for help to understand this to native English speaking colleagues.

Posted: Tue Oct 07, 2008 3:10 pm
by 9232632
will take at look at the example info on the Perimeter function.

given that i have a bunch of points, i have a function that determines which 2 points should have a line between them (a segment of the ship hull). with these 2 points, i was hoping to be able to "plot" them on a chart and have a line drawn between them.

kind of like 0,0 to 1,1 then 1,1 to 2,2, etc. problem is that my function needs to specify which 2 points should have a line drawn between them, and they may not be added to the chart in any particular order. what i was imagining was a function like AddLine (x1,y1,x2,y2) or AddXY (x1,y1), AddXY (x2,y2), DrawLine (x1,y1,x2,y2).

Posted: Tue Oct 07, 2008 3:41 pm
by narcis
Hi rperkins,

Yes, you can always use an additional series for plotting the line you request using its AddXY method and setting XValues.Order to none before populating it:

Code: Select all

  Series1.XValues.Order:=loNone;
Also you can use custom drawing on TeeChart's canvas, for example:

Code: Select all

procedure TForm1.Chart1AfterDraw(Sender: TObject);
begin
  Chart1.Canvas.Line(0,0,100,100);
end;
However, if perimeter function was what you needed then you shouldn't have to care about the points that form it.

Posted: Tue Oct 07, 2008 4:21 pm
by 9232632
the problem i'm facing is that as i'm "walking around the hull of the ship", there are some cases where i simply can't go "up" to the next point, i have to go back to the centerline. that's where the example of the Q-tip comes in to play. the algorithm i have says that as you're walking CCW from 0,0 and going up and out, if you get to a point where there's a point at x=0 and your current height, you have to go back to the centerline, then up at x=0, then back out to the point at the same height, but out near where you "left off". if there wasn't a point at x=0, then continue up and either in or out. if you get to the highest point, then go left, back to the centerline. then down, back to 0,0.

so, the ordering and placement of the points, and their corresponding lines matters.

all the "behind the scenes" processing, where i gather the points, and determine the lines (segments), and walking the hull are to be part of a much larger application (3 apps, 10+ DLLs, and tons of other code). i have to prove that my algorithms work before they'll let me add the functions to the "motherlode". this is where the TChart functionality comes in. i have been able to plot the points that make up my "section", but, now would like to see if the line segment processing is working.

Posted: Wed Oct 08, 2008 11:27 am
by narcis
Hi rperkins,

Please confirm if you think this suggestion might provide what you need:

- Plot x,y points you need using point Series
- Use TeeChart's Axis or Series positioning methods (see CalcXPos/CalcYPos, CalcXPosValue/CalcYPosValue, XScreenToValue, etc) to return the screen pixel locations for the lines you wish to plot. You can dynamically return point location for any Series point or Axis location.
- Use TeeChart's Canvas LineTo method to draw Lines. Use MoveTo to move to a new location without plotting a joining line (or alternatively use the 'Line' method directly) thus plotting the perimeter lines you require.

TeeChart's Tutorial 13 includes some examples of this.

Posted: Wed Oct 08, 2008 12:22 pm
by 9232632
that is the exact algorithm i was planning on implementing today.

thanks for confirming the approach.

:) :)

tried to implement the "solution", but haven't seen any lines being drawn, yet. also, tried to find the Tutorials, but was unable.

below is a function that was written to add 2 points to a series, and, then attempt to draw a line between them ... the Line and MoveTo/LineTo are redundant, but wanted to see if either would produce a line.

in another post, it was indicated that the line drawing had to be done in the OnAfterDraw event handler. well, i tried that, as well - still with no luck (copied the last 4 lines to the handler). the problem with doing this in the handler, i'd have to maintain a list of lines that i'd like to have drawn - some points would have multiple lines drawn to/from them. some points wouldn't be processed in order.

------------------DrawLine function-------------------------
void __fastcall TfrmPointPlot::DrawLine ( TChart *chart, TPointSeries *series,
double point1X, double point1Y,
double point2X, double point2Y )
{
// first, plot the 2 sets of points. (this works)
int id1 = series->AddXY ( point1X, point1Y );
int id2 = series->AddXY ( point2X, point2Y );

//********added Draw to force a draw - this results in the point values
//********being available to the functions below
// force a draw of the chart
chart->Draw();

// since there isn't a DrawLine method on the chart, directly, we have to get the
// coordinates of the points (as they are defined on the canvas), and use the canvas
// line function to draw the line

// get the actual canvas coordinates of the points (these are INTs).
coord1X = series->CalcXPos(id1);
coord1Y = series->CalcYPos(id1);
coord2X = series->CalcXPos(id2);
coord2Y = series->CalcYPos(id2);

// also tried...but always returned 0 for all 4 coord values
// coord1X = series->CalcXPosValue(point1X);
// coord1Y = series->CalcYPosValue(point1Y);
// coord2X = series->CalcXPosValue(point2X);
// coord2Y = series->CalcYPosValue(point2Y);

chart->Canvas->Pen->Color = clBlack;

// draw a line between the 2 points.
chart->Canvas->Line(coord1X,coord1Y,coord2X,coord2Y);

// redundant for the single line of code above, but neither worked.
chart->Canvas->MoveTo(coord1X,coord1Y);
chart->Canvas->LineTo(coord2X,coord2Y);

//*********still no lines being drawn on the chart
}

Posted: Thu Oct 09, 2008 4:33 pm
by 9232632
i added a chart->Draw() after the AddXY's, which resulted in values now being available from the CalcXPos and CalcYPos. they appear to be correct (x=0 --> 41, Y=#1 --> 206, Y=#2 --> 360. i would have figured that now having values for the Line and/or MoveTo/LineTo calls would have produced the lines.

Posted: Fri Oct 10, 2008 8:54 am
by narcis
Hi rperkins,
tried to implement the "solution", but haven't seen any lines being drawn, yet. also, tried to find the Tutorials, but was unable.
Tutorials should be found at TeeChart's program group, Start Menu -> All Programs -> Steema TeeChart 8.02 for Delphi 2007 and also at the Docs folder created by TeeChart's binary installers. Sourcecode installer doesn't contain any documentation nor examples.
below is a function that was written to add 2 points to a series, and, then attempt to draw a line between them ... the Line and MoveTo/LineTo are redundant, but wanted to see if either would produce a line.
Yes, as mentioned in previous message, Line method is the equivalent of combining MoveTo and LineTo.
in another post, it was indicated that the line drawing had to be done in the OnAfterDraw event handler. well, i tried that, as well - still with no luck (copied the last 4 lines to the handler). the problem with doing this in the handler, i'd have to maintain a list of lines that i'd like to have drawn - some points would have multiple lines drawn to/from them. some points wouldn't be processed in order.
Alernatively you can use Chart1->Draw() method call before the lines drawing code as you figured out later in the thread.
i added a chart->Draw() after the AddXY's, which resulted in values now being available from the CalcXPos and CalcYPos. they appear to be correct (x=0 --> 41, Y=#1 --> 206, Y=#2 --> 360. i would have figured that now having values for the Line and/or MoveTo/LineTo calls would have produced the lines.
So can you please confirm that you already have the lines in the chart as you wished?

Thanks in advance.

Posted: Fri Oct 10, 2008 12:29 pm
by 9232632
so far, i haven't been able to "produce" the lines.

Posted: Fri Oct 10, 2008 1:59 pm
by narcis
Hi rperkins,

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.

Posted: Fri Oct 10, 2008 2:40 pm
by 9232632
uploaded a zip file with the source and test files - interp.zip. if you run the Interp.exe application, it's pre-loaded with a test case, but the paths will probably be different. click on the Less Dense File button and select either of the 2 less dense files in the Data Files directory. click on the More Dense File button and select a "similar" data file (LD-100.22 goes with D-98.12, and LD-24.63 goes with D-22.53). for the 98/100 pair, use 100.00 as the distance, and 23.00 for the other pair. click on Process, you'll see the graphical results.

the file that has the functions that perform the DrawLine function is PlotPoint.cpp.

hopefully, it's something simple - like a setting, or a property.

Posted: Fri Oct 10, 2008 3:38 pm
by narcis
Hi rperkins,

Thanks for the example project but I wasn't able to run it here. After removing several package references we don't have here I came across with this message:

[Linker Fatal Error] Fatal: Unable to open file 'RZEDIT.OBJ'

Could you please let us know how should I solve this issue to run the project here or arrange a simple example project we can run "as-is"?

Thanks in advance.