Advertisement
WarPie90

[Simba 2.0] Random weighted point

Jan 2nd, 2025 (edited)
819
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 4.39 KB | None | 0 0
  1. program new;
  2.  
  3. (*
  4.   Generates a random point within the (convex)polygon/quad/triangle, drawn towards a Target point.
  5.  
  6.   Parameters:
  7.  
  8.   * Target: The point towards which the distribution is drawn.
  9.   * weight: Controls the strength of attraction towards the Target (higher values = stronger attraction).
  10.             - weight = 0 gives a uniform distribution.
  11.   * bias:   Introduces a Gaussian spread around the Target (higher values = wider spread).
  12.             - bias = 0 gives a purely weighted distribution towards the Target.
  13.  
  14.   Should expose weight and bias to the user if used as mouse distribution method. weight of 10 might be a little high.
  15. *)
  16.  
  17. function PolygonNearestEdge(Polygon: TPointArray; P: TPoint): TPoint;
  18. var
  19.   dist, best: single;
  20.   I: Integer;
  21.   q: TPoint;
  22. begin
  23.   Best   := $FFFFFF;
  24.   Result := Polygon[0];
  25.   for I := 0 to High(Polygon) do
  26.   begin
  27.     dist := DistToLine(p, Polygon[i], Polygon[(i+1) mod Length(Polygon)], q);
  28.     if (dist < best) then
  29.     begin
  30.       Best   := dist;
  31.       Result := q;
  32.     end;
  33.   end;
  34. end;
  35.  
  36.  
  37. function TTriangle.RandomWeightedPoint(Target: TPoint; weight: Single=10.0; bias: Single=1): TPoint;
  38. var
  39.   r1, r2, r3, u, v, w, t, sum: Single;
  40.   stdev,xr,yr: Single;
  41. const
  42.   eps := 0.0000001;
  43. begin
  44.   if bias > 0 then
  45.   begin
  46.     xr := abs(Self.A.x - Target.x) + abs(Self.B.x - Target.x) + abs(Self.C.x - Target.x);
  47.     yr := abs(Self.A.y - Target.y) + abs(Self.B.y - Target.y) + abs(Self.C.x - Target.y);
  48.  
  49.     Target.X += Round(GaussRand(0, xr/3 * bias) / weight);
  50.     Target.Y += Round(GaussRand(0, yr/3 * bias) / weight);
  51.   end;
  52.  
  53.   if not (Target in Self) then
  54.     Target := Self.NearestEdge(Target);
  55.  
  56.   r1 := Random();
  57.   r2 := Random();
  58.   if r1 + r2 > 1 then
  59.   begin
  60.     r1 := 1 - r1;
  61.     r2 := 1 - r2;
  62.   end;
  63.  
  64.   r3 := Random();
  65.   sum := (r1 + r2 + (1 - r1 - r2) + weight * r3) + eps;
  66.   u := r1 / sum;
  67.   v := r2 / sum;
  68.   w := (1 - r1 - r2) / sum;
  69.   t := (weight * r3) / sum;
  70.  
  71.   with Self do
  72.   begin
  73.     Result.X := Round(u * A.X + v * B.X + w * C.X + t * Target.X);
  74.     Result.Y := Round(u * A.Y + v * B.Y + w * C.Y + t * Target.Y);
  75.   end;
  76. end;
  77.  
  78. // do a polygon type or.. just rename to PolygonR...
  79. function TPointArray.RandomWeightedPoint(Target: TPoint; weight: Single=10.0; bias: Single=1): TPoint;
  80. var
  81.   i: Integer;
  82.   tri: TTriangleArray;
  83.   xr,yr,b,sum, r, stdev, area: Single;
  84. begin
  85.   area := PolygonArea(Self);
  86.  
  87.   if bias > 0 then
  88.   begin
  89.     for i := 0 to High(Self) do xr += abs(Self[i].x - Target.x);
  90.     xr /= Length(self);
  91.  
  92.     for i := 0 to High(Self) do yr += abs(Self[i].y - Target.y);
  93.     yr /= Length(self);
  94.  
  95.     Target.X += Round(GaussRand(0, xr * bias) / weight);
  96.     Target.Y += Round(GaussRand(0, yr * bias) / weight);
  97.   end;
  98.  
  99.   if not PointInPolygon(Target, Self) then
  100.     Target := PolygonNearestEdge(Self,Target);
  101.  
  102.   for i := 0 to High(Self) do
  103.     tri += TTriangle.Create(Target, Self[i], Self[(i+1) mod Length(Self)]);
  104.  
  105.   r := Random() * area;
  106.   sum := 0;
  107.   for i := 0 to High(tri) do
  108.   begin
  109.     sum += tri[i].Area;
  110.     if r < sum then
  111.       Exit(tri[i].RandomWeightedPoint(Target, weight, 0));
  112.   end;
  113. end;
  114.  
  115. function TQuad.RandomWeightedPoint(Target: TPoint; weight: Single=10.0; bias: Single=1): TPoint;
  116. begin
  117.   Result := Self.Corners.RandomWeightedPoint(Target, weight, bias);
  118. end;
  119.  
  120.  
  121. var
  122.   t, p: TPoint;
  123.   Tri: TTriangle;
  124.   Image: TImage;
  125.   hsl: TColorHSL;
  126.   mat: TSingleMatrix;
  127.   weight: Single := 10.0;
  128.   pts,poly: TPointArray;
  129. begin
  130.   Tri := [[100,200],[800,100],[700,400]];
  131.  
  132.   pts  := RandomTPA(7, [200,200,500,500]);
  133.   poly := pts.ConvexHull();
  134.  
  135.   Writeln(poly);
  136.  
  137.   Image := TImage.Create(800,800);
  138.   Image.DrawPolygon(tri.Corners);
  139.   Image.Show();
  140.  
  141.   while True do
  142.   begin
  143.     SetLength(mat, 0,0);
  144.     mat.SetSize(800,800);
  145.  
  146.     t := Target.MouseXY;
  147.     for 0 to 20000 do
  148.     begin
  149.       p := Tri.RandomWeightedPoint(T, weight, 0.5);
  150.  
  151.       if Image.InImage(p.x-1,p.y-1) and Image.InImage(p.x+1,p.y+1) then
  152.       begin
  153.         mat[p.y+1,p.x] += 1;
  154.         mat[p.y-1,p.x] += 1;
  155.         mat[p.y,p.x+1] += 1;
  156.         mat[p.y,p.x-1] += 1;
  157.         mat[p.y,p.x] += 1;
  158.       end;
  159.     end;
  160.  
  161.     WriteLn(weight);
  162.  
  163.     if Target.MousePressed(EMouseButton.LEFT)  then weight += 0.1;
  164.     if Target.MousePressed(EMouseButton.Right) then weight -= 0.1;
  165.  
  166.  
  167.     Image.FromMatrix(mat);
  168.     Image.DrawPolygon(Tri.Corners);
  169.     Image.Show(False);
  170.   end;
  171. end.
  172.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement