79302462

Date: 2024-12-23 07:42:24
Score: 0.5
Natty:
Report link

There are so many issues when managing arcs, but @chris answer above made sense to me.

I've added a counter-clockwise argument to the bounds and corrected an error in one of the arrays. The function has minor fixes and has been battle tested in a CAD app. Works great.

Below is a clip from an Arc class with start and end angles (sa, ea) and ccw property. Start and end angles are simply reversed for ccw arcs.

bounds():Segment {

    this.normalizeAngles();

    const start = this.ccw ? this.ea : this.sa;
    const end = this.ccw ? this.sa : this.ea;

    const iniQuad = this.getQuadrant(start);
    const endQuad = this.getQuadrant(end);

    const r = this.r;

    const ix = Math.cos(start) * this.r;
    const iy = Math.sin(start) * this.r;
    const ex = Math.cos(end) * this.r;
    const ey = Math.sin(end) * this.r;

    const minX = Math.min(ix, ex);
    const minY = Math.min(iy, ey);
    const maxX = Math.max(ix, ex);
    const maxY = Math.max(iy, ey);
    
    const xMax = [[maxX, r, r, r], [maxX, maxX, r, r], [maxX, maxX, maxX, r], [maxX, maxX, maxX, maxX]];
    const yMax = [[maxY, maxY, maxY, maxY], [r, maxY, r, r], [r, maxY, maxY, r], [r, maxY, maxY, maxY]];
    const xMin = [[minX, -r, minX, minX], [minX, minX, minX, minX], [-r, -r, minX, -r], [-r, -r, minX, minX]];
    const yMin = [[minY, -r, -r, minY], [minY, minY, -r, minY], [minY, minY, minY, minY], [-r, -r, -r, minY]];

    const x1 = xMin[endQuad][iniQuad];
    const y1 = yMin[endQuad][iniQuad];
    const x2 = xMax[endQuad][iniQuad];
    const y2 = yMax[endQuad][iniQuad];

    return new Segment(
        new Point(this.c.x + x1, this.c.y + y1), 
        new Point(this.c.x + x2, this.c.y + y2)
    );
}

private getQuadrant(angle:number) {
    const PI = Math.PI;
    const HALF_PI = Math.PI / 2;
    const TWO_PI = Math.PI * 2;
    if (angle > TWO_PI) angle = angle % TWO_PI;
    if (angle >= 0 && angle < HALF_PI) return 0;
    if (angle >= HALF_PI && angle < PI) return 1;
    if (angle >= PI && angle < (PI + HALF_PI)) return 2;
    return 3;
};

normalizeAngles() {
        this.sa = this.normalizeAngle(this.sa);
        this.ea = this.normalizeAngle(this.ea);
        if (this.sa >= this.ea) this.ea += Math.PI * 2;
    }

normalizeAngle(angle:number):number {
        let remainder = angle % (2 * Math.PI);
        if (remainder < 0) remainder += 2 * Math.PI;
        return remainder;
    }
Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @chris
  • Low reputation (1):
Posted by: markus