Skip to content

Commit e4da699

Browse files
authored
Merge pull request #6122 from calebfoss/transformations_for_accessible_outputs
Factor transformations into position and area for shapes' accessible outputs - addresses #4721
2 parents 35ec2c1 + 5a09fa4 commit e4da699

File tree

1 file changed

+55
-18
lines changed

1 file changed

+55
-18
lines changed

src/accessibility/outputs.js

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,8 @@ p5.prototype._accsOutput = function(f, args) {
347347
//get lenght
348348
include.length = Math.round(this.dist(args[0], args[1], args[2], args[3]));
349349
//get position of end points
350-
let p1 = _getPos([args[0], [1]], this.width, this.height);
351-
let p2 = _getPos([args[2], [3]], this.width, this.height);
350+
let p1 = this._getPos(args[0], [1]);
351+
let p2 = this._getPos(args[2], [3]);
352352
include.loc = _canvasLocator(middle, this.width, this.height);
353353
if (p1 === p2) {
354354
include.pos = `at ${p1}`;
@@ -363,11 +363,11 @@ p5.prototype._accsOutput = function(f, args) {
363363
//make color fill
364364
include.color = this.ingredients.colors.fill;
365365
//get area of shape
366-
include.area = _getArea(f, args, this.width, this.height);
366+
include.area = this._getArea(f, args);
367367
}
368368
//get middle of shapes
369369
//calculate position using middle of shape
370-
include.pos = _getPos(middle, this.width, this.height);
370+
include.pos = this._getPos(...middle);
371371
//calculate location using middle of shape
372372
include.loc = _canvasLocator(middle, this.width, this.height);
373373
}
@@ -422,33 +422,40 @@ function _getMiddle(f, args) {
422422
}
423423

424424
//gets position of shape in the canvas
425-
function _getPos(args, canvasWidth, canvasHeight) {
426-
if (args[0] < 0.4 * canvasWidth) {
427-
if (args[1] < 0.4 * canvasHeight) {
425+
p5.prototype._getPos = function (x, y) {
426+
const untransformedPosition = new DOMPointReadOnly(x, y);
427+
const currentTransform = this._renderer.isP3D ?
428+
new DOMMatrix(this._renderer.uMVMatrix.mat4) :
429+
this.drawingContext.getTransform();
430+
const { x: transformedX, y: transformedY } = untransformedPosition
431+
.matrixTransform(currentTransform);
432+
const { width: canvasWidth, height: canvasHeight } = this;
433+
if (transformedX < 0.4 * canvasWidth) {
434+
if (transformedY < 0.4 * canvasHeight) {
428435
return 'top left';
429-
} else if (args[1] > 0.6 * canvasHeight) {
436+
} else if (transformedY > 0.6 * canvasHeight) {
430437
return 'bottom left';
431438
} else {
432439
return 'mid left';
433440
}
434-
} else if (args[0] > 0.6 * canvasWidth) {
435-
if (args[1] < 0.4 * canvasHeight) {
441+
} else if (transformedX > 0.6 * canvasWidth) {
442+
if (transformedY < 0.4 * canvasHeight) {
436443
return 'top right';
437-
} else if (args[1] > 0.6 * canvasHeight) {
444+
} else if (transformedY > 0.6 * canvasHeight) {
438445
return 'bottom right';
439446
} else {
440447
return 'mid right';
441448
}
442449
} else {
443-
if (args[1] < 0.4 * canvasHeight) {
450+
if (transformedY < 0.4 * canvasHeight) {
444451
return 'top middle';
445-
} else if (args[1] > 0.6 * canvasHeight) {
452+
} else if (transformedY > 0.6 * canvasHeight) {
446453
return 'bottom middle';
447454
} else {
448455
return 'middle';
449456
}
450457
}
451-
}
458+
};
452459

453460
//locates shape in a 10*10 grid
454461
function _canvasLocator(args, canvasWidth, canvasHeight) {
@@ -469,7 +476,7 @@ function _canvasLocator(args, canvasWidth, canvasHeight) {
469476
}
470477

471478
//calculates area of shape
472-
function _getArea(objectType, shapeArgs, canvasWidth, canvasHeight) {
479+
p5.prototype._getArea = function (objectType, shapeArgs) {
473480
let objectArea = 0;
474481
if (objectType === 'arc') {
475482
// area of full ellipse = PI * horizontal radius * vertical radius.
@@ -526,8 +533,38 @@ function _getArea(objectType, shapeArgs, canvasWidth, canvasHeight) {
526533
) / 2;
527534
// (Ax( By − Cy) + Bx(Cy − Ay) + Cx(Ay − By ))/2
528535
}
529-
530-
return Math.round(objectArea * 100 / (canvasWidth * canvasHeight));
531-
}
536+
// Store the positions of the canvas corners
537+
const canvasWidth = this.width * this._pixelDensity;
538+
const canvasHeight = this.height * this._pixelDensity;
539+
const canvasCorners = [
540+
new DOMPoint(0, 0),
541+
new DOMPoint(canvasWidth, 0),
542+
new DOMPoint(canvasWidth, canvasHeight),
543+
new DOMPoint(0, canvasHeight)
544+
];
545+
// Apply the inverse of the current transformations to the canvas corners
546+
const currentTransform = this._renderer.isP3D ?
547+
new DOMMatrix(this._renderer.uMVMatrix.mat4) :
548+
this.drawingContext.getTransform();
549+
const invertedTransform = currentTransform.inverse();
550+
const tc = canvasCorners.map(
551+
corner => corner.matrixTransform(invertedTransform)
552+
);
553+
/* Use same shoelace formula used for quad area (above) to calculate
554+
the area of the canvas with inverted transformation applied */
555+
const transformedCanvasArea = Math.abs(
556+
(tc[3].x + tc[0].x) * (tc[3].y - tc[0].y) +
557+
(tc[0].x + tc[1].x) * (tc[0].y - tc[1].y) +
558+
(tc[1].x + tc[2].x) * (tc[1].y - tc[2].y)+
559+
(tc[2].x + tc[3].x) * (tc[2].y - tc[3].y)
560+
) / 2;
561+
/* Compare area of shape (minus transformations) to area of canvas
562+
with inverted transformation applied.
563+
Return percentage */
564+
const untransformedArea = Math.round(
565+
objectArea * 100 / (transformedCanvasArea)
566+
);
567+
return untransformedArea;
568+
};
532569

533570
export default p5;

0 commit comments

Comments
 (0)