Page 1 of 1

Selecting multiple shapes in TMapSeries with mouse drag

Posted: Tue Aug 02, 2011 7:06 am
by 10555193
Hello,

I would like to get some pointers to implement a feature one of our customers needs. They would like to select (using mouse drag and showing a selection box) a number of shapes in a TMapSeries.
I would like to add this feature as a tool.
Specific questions are:
I have looked at the zoom function which behaves like I would like the selection to behave and would like to use that information (the box) to determine all the shapes that completely fit in the box.
My specific questions:
How do I transform mouse coordinates to the viewport coordinates so I can see what shapes lie within the selection box?
How do I overrule the zoom mechanism to become a selection mechanism?
We will be using the latest version of TeeCharts.

Thanks in advance,
Michael.

Re: Selecting multiple shapes in TMapSeries with mouse drag

Posted: Tue Aug 02, 2011 2:19 pm
by yeray
Hello Michael,

If I understood it correctly you could do it as follows:

Code: Select all

uses Series, TeeMapSeries, TeCanvas, Math;

var MouseDownX, MouseDownY: Integer;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1.View3D:=false;
  Chart1.Legend.Visible:=false;
  Chart1.AllowPanning:=pmNone;
  Chart1.AllowZoom:=false;

  Chart1.AddSeries(TMapSeries).FillSampleValues(15);

  MouseDownX:=-1;
  MouseDownY:=-1;
end;

procedure TForm1.Chart1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  MouseDownX:=X;
  MouseDownY:=Y;
end;

procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var tmpRect: TRect;
    tmpMap: TMapSeries;
    tmpPoint: TPoint;
    tmpInside: Boolean;
    i, j: Integer;
begin
  if ((MouseDownX > -1) and (MouseDownY > -1)) then
  begin
    tmpRect:=Rect(Min(MouseDownX, X), Min(MouseDownY, Y), Max(MouseDownX, X), Max(MouseDownY, Y));
    tmpMap:=Chart1[0] as TMapSeries;
    for i:=0 to tmpMap.Count-1 do
    begin
      tmpInside:=false;
      for j:=0 to tmpMap.Shapes[i].Points.Count-1 do
      begin
        tmpPoint:=tmpMap.Shapes[i].Points.Polygon.GetPoints[j];
        if (PointInRect(tmpRect,tmpPoint)) then
        begin
          tmpInside:=true;
          break;
        end;
      end;
      if (tmpInside) then
        tmpMap.Shapes[i].Color:=clYellow
      else
        tmpMap.Shapes[i].Color:=clTeeColor;
    end;

    with Chart1.Canvas do
    begin
      Brush.Style:=bsClear;
      Pen.Color:=clGrayText;
      Chart1.Repaint;
      Rectangle(tmpRect);
    end;
  end;
end;

procedure TForm1.Chart1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  MouseDownX:=-1;
  MouseDownY:=-1;
end;
I've disabled zoom and scroll features and I draw the rectangle manually with the Mouse events. I also calculate what shapes have a point inside the rectangle and I change their color.

Re: Selecting multiple shapes in TMapSeries with mouse drag

Posted: Wed Aug 03, 2011 8:36 am
by 10555193
Hello Yeray,

This is indeed what I was looking for. And it even works pretty well with large amounts of shapes. Thanks this will save me a lot of time and it can easily be fit into our current functions. I'll see if I can make it into a tool that you can add to a chart.

Thanks,
Michael.

Re: Selecting multiple shapes in TMapSeries with mouse drag

Posted: Wed Sep 28, 2011 2:55 pm
by 10555193
I have implemented your solution into our application but when some of my customers wanted to have gradients on the shapes and gradients in the background, shadow effects and highlighted borders the redraw got exceedingly slower. Since this is done every time one shape is selected/deselected this can amount to quite a backlog. Sometimes can take more than 2 second with only three shapes visible.
Is it possible to only update one shape without having to redraw all the other shapes in a series?

Re: Selecting multiple shapes in TMapSeries with mouse drag

Posted: Thu Sep 29, 2011 8:21 am
by narcis
Hi Michael,

I guess the problem here is due to custom canvas drawing which requires repainting the chart to run smoothly. This draws the selection rectangle. If you don't need to paint it your application may run quicker. I this doesn't suffice please attach a simple example project we can run "as-is" to reproduce the problem here and we will have a look and see if we can find a way to improve performance.

Re: Selecting multiple shapes in TMapSeries with mouse drag

Posted: Fri Sep 30, 2011 8:06 am
by 10555193
Hello NarcĂ­s,

I have attached the version of my program to this post. The problems start to form when I use the GDI plus for better image quality. Would it be possible to get the selection box shown on the chart as it shows on the non-gdi plus version. What I also see that the gdi plus version draws a lot slower, I understand that it does a lot more than the normal drawing but I had not expected it to be this much. I have removed the gdi plus from my application which helps a lot with regards to repainting.

Thanks again for the help,
Michael

Re: Selecting multiple shapes in TMapSeries with mouse drag

Posted: Fri Sep 30, 2011 11:52 am
by narcis
Hi Michael,
Would it be possible to get the selection box shown on the chart as it shows on the non-gdi plus version.
I'm afraid there's a bug with GDI+ canvas which I have added (TV52015765) to the defect list to be investigated. In the meantime, I found that setting Canvas.Pen.Mode to pmNotXor works fine:

Code: Select all

    Chart2.Canvas.Pen.Mode:=pmNotXor;
What I also see that the gdi plus version draws a lot slower, I understand that it does a lot more than the normal drawing but I had not expected it to be this much.
We are constantly trying to improve TeeChart performance but this is only possible to some extent as in most circumstances GDI+ is known to be slower than GDI.