Recent

Author Topic: BGRABitmap Feature request : isPointInRange  (Read 4193 times)

aradeonas

  • Hero Member
  • *****
  • Posts: 824
BGRABitmap Feature request : isPointInRange
« on: November 06, 2014, 08:21:57 pm »
Hi,
I made a test project that should change color when mouse pointer is in range of icon, with isPointInPath return true if only point in in path but I need an function that return true when point is in minimum area that include all of bitmap.
I attached a test project and screenshot to show what I mean.

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: BGRABitmap Feature request : isPointInRange
« Reply #1 on: November 06, 2014, 11:47:20 pm »
I don't think there is a simple way to do such a function. However you can do that by defining the path of the outline after drawing the shape (and by setting the boolean whether the mouse is hovering before calling redraw):
Code: [Select]
procedure TForm1.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
var
  center: TPointF;
begin
  content := TBGRABitmap.Create(Bitmap.Width, Bitmap.Height, BGRAPixelTransparent);
  ctx := content.Canvas2D;
  ctx.antialiasing := True;
  ctx.pixelCenteredCoordinates := True;

  //Draw
  center := pointf(ctx.Width / 2, ctx.Height / 2);
  ctx.translate(center.X, center.Y);
  ctx.save();
  ctx.scale(4, 4);
  ctx.strokeStyle('rgba(0,0,0,0)');
  ctx.miterLimit := 4;
  ctx.save();
  ctx.beginPath();
  ctx.moveTo(37.324, 10.004);
  ctx.bezierCurveTo(31.802, 0.43799999999999883, 19.569, -2.84, 10.003999999999998, 2.6839999999999993);
  ctx.bezierCurveTo(0.438, 8.206, -2.84, 20.438, 2.684, 30.004);
  ctx.bezierCurveTo(8.206, 39.569, 20.438000000000002, 42.847, 30.004, 37.324);
  ctx.bezierCurveTo(39.569, 31.801, 42.848, 19.569, 37.324, 10.004);
  ctx.closePath();
  ctx.moveTo(28.004, 33.859);
  ctx.bezierCurveTo(20.352, 38.278, 10.566000000000003, 35.656, 6.148, 28.003);
  ctx.bezierCurveTo(1.729, 20.351, 4.351999999999999, 10.565000000000001, 12.004, 6.148);
  ctx.bezierCurveTo(19.656, 1.729, 29.442, 4.351, 33.86, 12.004);
  ctx.bezierCurveTo(38.278, 19.656, 35.656, 29.441, 28.004, 33.859);
  ctx.closePath();
  ctx.moveTo(27.204, 19.191);
  ctx.lineTo(16.731, 13.082999999999998);
  ctx.bezierCurveTo(15.777000000000001, 12.525999999999998, 15.007000000000001, 12.970999999999998, 15.012000000000002, 14.075);
  ctx.lineTo(15.066000000000003, 26.198999999999998);
  ctx.bezierCurveTo(15.071000000000003, 27.302999999999997, 15.850000000000003, 27.752, 16.807000000000002, 27.198999999999998);
  ctx.lineTo(27.200000000000003, 21.198999999999998);
  ctx.bezierCurveTo(28.156, 20.647, 28.158, 19.748, 27.204, 19.191);
  ctx.closePath();

  if b then ctx.fillStyle('#F26767') else ctx.fillStyle('#3f5e99');
  ctx.fill();

  ctx.beginPath();
  ctx.moveTo(37.324, 10.004);
  ctx.bezierCurveTo(31.802, 0.43799999999999883, 19.569, -2.84, 10.003999999999998, 2.6839999999999993);
  ctx.bezierCurveTo(0.438, 8.206, -2.84, 20.438, 2.684, 30.004);
  ctx.bezierCurveTo(8.206, 39.569, 20.438000000000002, 42.847, 30.004, 37.324);
  ctx.bezierCurveTo(39.569, 31.801, 42.848, 19.569, 37.324, 10.004);
  ctx.closePath();

  ctx.restore();

  Bitmap.PutImage(0, 0, content, dmDrawWithTransparency);
 // content.Free;
end;

procedure TForm1.BGRAVirtualScreen1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
begin
      mx := X;
  my := Y;
  if ctx <> nil then
    if ctx.isPointInPath(X+0.5, Y+0.5) then
    begin
      if not b then
      begin
        b := True;
        BGRAVirtualScreen1.RedrawBitmap;
      end;
    end
    else
    begin
      if b then
      begin
        b := False;
        BGRAVirtualScreen1.RedrawBitmap;
      end;
    end;
end;
Conscience is the debugger of the mind

aradeonas

  • Hero Member
  • *****
  • Posts: 824
Re: BGRABitmap Feature request : isPointInRange
« Reply #2 on: November 07, 2014, 09:38:47 am »
Quote
I don't think there is a simple way to do such a function.
Yes I agree,and your code works. I am thinking about a way to find out a way to find points to make main path for this (because they are not always circle).
If you have an idea about this please let me know.

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: BGRABitmap Feature request : isPointInRange
« Reply #3 on: November 07, 2014, 07:34:25 pm »
Well finding the bounding box is easy. Maybe determine the shape with the biggest bounding box. But for example with the "pause" symbol, it will not give anything interesting because it is in multiple parts. What you are looking for is the convex hull:
http://en.wikipedia.org/wiki/Convex_hull
Conscience is the debugger of the mind

aradeonas

  • Hero Member
  • *****
  • Posts: 824
Re: BGRABitmap Feature request : isPointInRange
« Reply #4 on: November 07, 2014, 07:44:41 pm »
good. I am working in an other part of project, I will come back and test ideas about this subject.
But problem is all ideas I have,need allot of process and its not good. Its the reason I ask you because you are a master in this field ;)
Thank you and if I can do anything good I share it and if you get a new idea please let me know

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: BGRABitmap Feature request : isPointInRange
« Reply #5 on: November 07, 2014, 11:21:23 pm »
Alright!  :)
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018