Good idea Jeremy (it had kind of crossed my mind to do that anyway).
I’m not a teacher by nature, so any comments/advice on clarity/ease-of-understanding woud be helpful.
Meanwhile, here’s an example of using PMatrix2D to map from within a matrix to screen points…
// This is an example of how to map from points calculated in one matrix to
// another matrix. It is a simple visualisation of inputs from two IR
// distance sensors (although we're not going to read any sensors - we'll
// just hardcode the values, for now).
// Each "sensor" is positioned at an angle and represented by a blue rectangle
// The distance from each "sensor" to a detected object is represented by a
// green line drawn perpendicular to the "sensor", with length DISTANCE_A or
// DISTANCE_B
// The code is dumb and simply assumes whatever is being detected is a straight
// wall, which runs (at least) between the endpoints of the green "distance"
// lines.
// The detected "wall" is represented by a red line drawn between those 2
// endpoints.
// Each "sensor" and "distance" line is drawn within its own matrix. The
// reason for that is it's easier to translate and rotate the canvas, than
// to mess around with trigonometry that would otherwise be involved due to
// the sensors being at an angle to each other - ANGLE_A and ANGLE B
// (note these are in mirrored positions - hence a positive angle and a
// negative angle).
//
// Although use of transform/rotate makes it easier to code the drawing of
// "sensors" and "distance" lines, there is a challenge in drawing the red
// "wall" line between the ends of the two "distance" lines -
// line(x1, y1, x2, y2).
//
// Can you specify a line's start point in one matrix, change matrix, then
// specify its end point? NO!
// (you must specify the start and end points in a SINGLE command)
//
// Fortunately we can use getMatrix() and multX()/multY() to map our endpoint
// to the screen....
// ONCE YOU GET THIS WORKING, TRY CHANGING THE VALUES FOR THE FOLLOWING
// - keep the values sensible ;-)
// ANGLE_A
// ANGLE_B
// DISTANCE_A
// DISTANCE_B
// (the red "wall" line should always join the ends of the 2 "distance" lines)
// Rectangle (sensor) size
int SENSOR_WIDTH = 50;
int SENSOR_HEIGHT = 20;
// Mid-point along rectangle (sensor) edge
int HALF_SENSOR_WIDTH = SENSOR_WIDTH / 2;
// Half the distance between the two "sensors"
int SENSOR_SEPARATION = 100;
// Sensor A angle
int ANGLE_A = -55;
// Sensor A distance (hardcoded for this example - no real input, here)
int DISTANCE_A = 450;
// Sensor B angle
int ANGLE_B = 55;
// Sensor B distance (hardcoded for this example - no real input, here)
int DISTANCE_B = 350;
void setup() {
PMatrix2D currMatrix;
float x1, y1, x2, y2;
// Set our canvas size and background colour (white)
size(800, 500);
background(255);
// Save initial matrix
pushMatrix();
// Create a common offset in which to draw each "sensor" & "distance"
translate(100, 250);
//////////////////////////////////////////////////////////////////////
// "SENSOR" A ////////////////////////////////////////////////////////
pushMatrix(); // Start a new matrix just for this "sensor"
// Move origin UP 100
translate(0,-SENSOR_SEPARATION);
// Rotate canvas to correct angle for this sensor
rotate(radians(ANGLE_A));
// Draw the "sensor"
stroke(0);
fill(0, 0, 255);
rect(0, 0, SENSOR_WIDTH,SENSOR_HEIGHT);
// Draw the "distance" line for this sensor
stroke(0,255,0);
line(HALF_SENSOR_WIDTH, SENSOR_HEIGHT, HALF_SENSOR_WIDTH, DISTANCE_A);
// Get the current matrix and use it to map the end of the "distance" line
// to a screen/top-level matrix point - using multX & multY on the endpoint
currMatrix = (PMatrix2D)getMatrix();
x1 = currMatrix.multX(HALF_SENSOR_WIDTH, DISTANCE_A);
y1 = currMatrix.multY(HALF_SENSOR_WIDTH, DISTANCE_A);
// Label it "A"
fill(255, 255, 255);
text("A", HALF_SENSOR_WIDTH - 5, SENSOR_HEIGHT - 5);
popMatrix(); // Finsh with this matrix
//////////////////////////////////////////////////////////////////////
// "SENSOR" B ////////////////////////////////////////////////////////
pushMatrix(); // Start a new matrix just for this "sensor"
// Move origin DOWN 100
translate(0,SENSOR_SEPARATION);
// Rotate canvas to correct angle for this sensor
rotate(radians(ANGLE_B));
// Draw the "sensor"
stroke(0);
fill(0, 0, 255);
rect(0,-SENSOR_HEIGHT, SENSOR_WIDTH, SENSOR_HEIGHT);
// Draw the "distance" line for this sensor
stroke(0,255,0);
line(HALF_SENSOR_WIDTH, -SENSOR_HEIGHT, HALF_SENSOR_WIDTH, -DISTANCE_B);
// Get the current matrix and use it to map the end of the "distance" line
// to a screen/top-level matrix point - using multX & multY on the endpoint
currMatrix = (PMatrix2D)getMatrix();
x2 = currMatrix.multX(HALF_SENSOR_WIDTH, -DISTANCE_B);
y2 = currMatrix.multY(HALF_SENSOR_WIDTH, -DISTANCE_B);
// Label it "B"
fill(255, 255, 255);
text("B", HALF_SENSOR_WIDTH - 5, -SENSOR_HEIGHT + 10);
popMatrix(); // Finsh with this matrix
//////////////////////////////////////////////////////////////////////
// "WALL" (line between the endpoints of the two "distance" lines ////
// x1,y1 was mapped from "sensor" A's matrix
// x2,y2 was mapped from "sensor" B's matrix
// Thanks to PMatrix2D & multX/multY those points are now screen points
popMatrix(); // Back to normal [undoes the initial translate(100, 250) ]
fill(0, 0, 255);
text(String.format("A: dist=%d\nmatrix-point=(%d, %d)\nmapped-point=(%d, %d)",
DISTANCE_A, HALF_SENSOR_WIDTH, DISTANCE_A, (int)x1, (int)y1), x1 + 5, y1 + 5);
text(String.format("B: dist=%d\nmatrix-point=(%d, %d)\nmapped-point=(%d, %d)",
DISTANCE_B, HALF_SENSOR_WIDTH, -DISTANCE_B, (int)x2, (int)y2), x2 + 5, y2 + 5);
stroke(255,0,0);
line(x1, y1, x2, y2);
}