1

I searched all internet and didn't find any pseudo code that solved this problem, I want to find an Arc between two points, A and B, using 5 arguments:

  1. Start Point
  2. End Point
  3. Radius (Don't know if this is needed)
  4. Angle
  5. Quality

Example:

img

StartPoint = The green point on the left is the Start Point set on the arguments

EndPoint = The green point on the right is the End Point set on the arguments

Angle = Angle of the Arc(Semi Circle)

Quality = How many red circles to create

I would like to have a pseudo code to solve this problem

Thanks in advance :D

Spektre
  • 49,595
  • 11
  • 110
  • 380
Mário Gabriel
  • 367
  • 1
  • 2
  • 13
  • what kind of arc? circular,elliptic... ? what about the start/end tangents ? see [Formula to draw arcs ending in straight lines, Y as a function of X, starting slope, ending slope, starting point and arc radius?](https://stackoverflow.com/a/22982623/2521214) – Spektre Jul 03 '17 at 07:50
  • Just a simple Semi-Circle, will i need them ? – Mário Gabriel Jul 03 '17 at 20:18
  • if by "them" you mean the tangents then no. This is doable without them too but in such case the start and end slope will be undefined which may cause problems for some tasks. So the question is do you need specific start or end slope or not ... – Spektre Jul 03 '17 at 21:46

1 Answers1

1

Let start point is P0, end point P1, angle Fi. R is not needed

At first find arc center. Get middle of P0-P1 segment.

 M = (P0 + P1) / 2 
 // M.x =  (P0.x + P1.x) / 2 , same for y

And direction vector

 D = (P1 - P0) / 2

Get length of D

 lenD = Math.Hypot(D.x, D.y)  //Vector.Length, sqrt of sum of squares

Get unit vector

 uD = D / lenD

Get (left) perpendicular vector

 (P.x, P.y) = (-uD.y, ud.x)

Now circle center

 if F = Pi then
     C.x = M.x
     C.y = M.y
 else
     C.x = M.x + P.x * Len / Tan(Fi/2)
     C.y = M.y + P.y * Len / Tan(Fi/2)

Vector from center to start point:

CP0.x = P0.x - C.x
CP0.y = P0.y - C.y

Then you can calculate coordinates of N intermediate points at the arc using rotation of vector CP0 around center point

 an = i * Fi / (NSeg + 1);
 X[i] = C.x + CP0.x * Cos(an) - CP0.y * Sin(an)
 Y[i] = C.y + CP0.x * Sin(an) + CP0.y * Cos(an)

Working Delphi code

procedure ArcByStartEndAngle(P0, P1: TPoint; Angle: Double; NSeg: Integer);
var
  i: Integer;
  len, dx, dy, mx, my, px, py, t, cx, cy, p0x, p0y, an: Double;
  xx, yy: Integer;
begin
  mx := (P0.x + P1.x) / 2;
  my := (P0.y + P1.y) / 2;

  dx := (P1.x - P0.x) / 2;
  dy := (P1.y - P0.y) / 2;

  len := Math.Hypot(dx, dy);

  px := -dy / len;
  py := dx / len;

  if Angle = Pi then
    t := 0
  else
    t := len / Math.Tan(Angle / 2);

  cx := mx + px * t;
  cy := my + py * t;

  p0x := P0.x - cx;
  p0y := P0.y - cy;

  for i := 0 to NSeg + 1 do begin

   an := i * Angle / (NSeg + 1);
   xx := Round(cx + p0x * Cos(an) - p0y * Sin(an));
   yy := Round(cy + p0x * Sin(an) + p0y * Cos(an));

   Canvas.Ellipse(xx - 3, yy - 3, xx + 4, yy + 4);
  end;
end;

Result for (Point(100, 0), Point(0, 100), Pi / 2, 8 (Y-axis down at the picture)

enter image description here

MBo
  • 77,366
  • 5
  • 53
  • 86
  • Well everything seems to be fine, but i am strugling with the last part the " rotation of C-P0 vector", could you verify to see if it is correct ? – Mário Gabriel Jul 03 '17 at 19:13
  • For a "semi-circle", the center is just the middle of the start-end segment. –  Jul 03 '17 at 22:33
  • @Mário Gabriel I changed the post drastically, checked for work. – MBo Jul 04 '17 at 06:28
  • @MBo Hey i changed my code and it works like yours http://i.imgur.com/L4znPGv.png, but i dont know if this is right though, cause look at this http://i.imgur.com/q5WcNa8.png Some examples: 200,400 to 400,200 = http://i.imgur.com/vDSjbuj.png 200,400 to 600,200 = http://i.imgur.com/2RVUg8N.png C# Code = https://hastebin.com/obeganuqaq.cs – Mário Gabriel Jul 04 '17 at 14:08
  • Remove `(float)Math.Round` if you need float coordinates. Mistake here with sign: Y = cy + p0x * (float)Math.Sin(an) **+** p0y * (float)Math.Cos(an); Also note - for intermediate points only use for (var i = **1**... with correction WorldPoints[i-1] = vector; – MBo Jul 04 '17 at 14:33
  • @MBo Works like a charm now, thanks so much and sorry for bothering you so much – Mário Gabriel Jul 04 '17 at 16:25