-1

I have the following code to draw circles, squares, ellipses and (wrong) rectangles with equal angle sections. Circles, squares and ellipses work fine, but what i want to achieve with the rectangle code is that the end of the sections lines don't end on the border of the ellipsis but on the border of the rectangle. Using the same code as I am using for the square isn't working because the lines will get stretched and the angles are wrong afterwards.

The ellipsis I am drawing looks like this, the orange lines show how the lines should be when I select the rectangle version ("R"):

ellipsis with rectangle lines:

ellipsis with rectangle lines

Code to get points for the current angle for the ellipsis, circle, square and rectangle
This will be called in a loop to get all points and draw lines between the coordinates.

    const a = width * 0.5;
    const b = height * 0.5;
    let x;
    let y;

    const ro =
        pieChartKind === 'E' || pieChartKind === 'R'
            ? (a * b) /
              Math.sqrt((b * Math.cos(currentAngle)) ** 2 + (a * Math.sin(currentAngle)) ** 2)
            : 1;

    const factor =
        pieChartKind === 'S' || pieChartKind === 'R'
            ? Math.sqrt(1.0) /
              Math.max(
                    Math.abs(ro * Math.cos(currentAngle)),
                    Math.abs(ro * Math.sin(currentAngle)),
              )
            : 1;

    if (pieChartKind === 'E') {
        x = factor * ro * Math.cos(currentAngle) + width * 0.5;
        y = factor * ro * Math.sin(currentAngle) + height * 0.5;
    } else {
        x = factor * ro * Math.cos(currentAngle) * a + width * 0.5;
        y = factor * ro * Math.sin(currentAngle) * b + height * 0.5;
    }

    return { x, y };
Spektre
  • 49,595
  • 11
  • 110
  • 380
somsam43
  • 9
  • 4

1 Answers1

0

For rectangle you can use this approach:

if (abs(a*cos(currentAngle)) >= abs(b*sin(currentAngle))) {
     if (cos(currentAngle) > 0) {
        x = 2*a
        y = b + a * tan(currentAngle) 
     }
     else {
        x = 0
        y = b - a * tan(currentAngle) 
}
else {
     if (sin(currentAngle) > 0) {  
        x = a + b / tan(currentAngle) 
        y = 0
     }
     else {
         x = a - b / tan(currentAngle) 
         y = 2*b
     }
 }

Logic here: radius-vector intersects vertical edge for angles close to X-axis, and horizontal edge for angles close to Y-axis.

Example implemented in Delphi, ellipse points ex, ey and rectangle points rx, ry are calculated relative to center.

enter image description here

var
  i, cx, cy, ex, ey, rx, ry, a, b: Integer;
  an: Double;
begin
  cx := 300; cy := 200;  a := 200;      b := 150;
  for i := 0 to 31 do begin
    an := i * 2 * Pi / 32;
    ex := Round(a * Cos(an));
    ey := Round(b * Sin(an));
    Canvas.Pen.Color := clBlue;
    Canvas.Pen.Width := 1;
    Canvas.MoveTo(cx, cy);
    Canvas.LineTo(cx + ex, cy + ey);
    if abs(a * Cos(an)) >= abs(b * Sin(an)) then begin
      if Cos(an) > 0 then begin
        rx := a;
        ry := Round(b * tan(an));
      end else begin
        rx := -a;
        ry := -Round(b * tan(an));
      end;
    end else begin
      if Sin(an) >= 0 then begin
        ry := b;
        rx := Round(a / tan(an));
      end else begin
        ry := -b;
        rx := -Round(a / tan(an));
      end;
    end;
    Canvas.Pen.Color := clRed;
    Canvas.Pen.Width := 2;
    Canvas.LineTo(cx + rx, cy + ry);
  end;
MBo
  • 77,366
  • 5
  • 53
  • 86
  • Sorry for the late response, I was on holidays and haven't had time to check in. I think your solution is for something different, at least it draws something completly different for me. I don't want to lose the ellipse shape, I just want the ends of each stroke to end on the rectangle rather than the ellipse. [Result](https://ibb.co/HYBpMWb) – somsam43 Sep 14 '22 at 18:37
  • Look at my picture. Here I calculate both ellipse points (blue lines) and corresponding rectangle lines (bold red ends). I – MBo Sep 15 '22 at 02:05
  • Thank you so much! I haven't had time to look at it in full detail but in general it looks exactly like i want and the angles are always the same and wont get pinched/stretched. I will have a more detailed look at it the upcoming days and will let you know if I have additional questions :D – somsam43 Sep 15 '22 at 07:05