Premature Optimization Triangle
Loading WASM module...
"Premature optimization is the root of all evil" — Donald Knuth
An interactive visualization built with C++ and WebAssembly that demonstrates the classic engineering tradeoff triangle. Drag the dot to explore how prioritizing different concerns affects your development approach.
The backend C++ logic just linear algebra to calculate positions based on user input. This was almost entirely AI generated:
C++
#include <emscripten/emscripten.h>
#include <cmath>
#include <algorithm>
// Optimized: Use simple structs without constructors for better performance
struct Point2D {
double x, y;
};
struct BarycentricCoord {
double performance;
double velocity;
double adaptability;
};
// Optimized: Inline math functions for speed
inline double distanceSq(double x1, double y1, double x2, double y2) {
double dx = x2 - x1;
double dy = y2 - y1;
return dx * dx + dy * dy;
}
inline double signedArea(double x1, double y1, double x2, double y2, double x3, double y3) {
return (x1 - x3) * (y2 - y3) - (x2 - x3) * (y1 - y3);
}
// Optimized: Store triangle as simple doubles instead of Point2D objects
static double topX, topY, leftX, leftY, rightX, rightY;
static double invTotalArea; // Pre-calculate inverse for division optimization
// Dot position and state
static BarycentricCoord dotPosition = {0.33, 0.33, 0.34};
static bool isDragging = false;
// Cached dot cartesian position to avoid recalculation
static double cachedDotX, cachedDotY;
static bool dotPositionDirty = true;
// Optimized: Inline barycentric to cartesian conversion
inline void updateDotCartesian() {
if (dotPositionDirty) {
cachedDotX = dotPosition.performance * topX +
dotPosition.velocity * leftX +
dotPosition.adaptability * rightX;
cachedDotY = dotPosition.performance * topY +
dotPosition.velocity * leftY +
dotPosition.adaptability * rightY;
dotPositionDirty = false;
}
}
// Optimized: Fast point-in-triangle test
inline bool isInsideTriangle(double px, double py) {
double d1 = signedArea(px, py, topX, topY, leftX, leftY);
double d2 = signedArea(px, py, leftX, leftY, rightX, rightY);
double d3 = signedArea(px, py, rightX, rightY, topX, topY);
bool hasNeg = (d1 < 0) || (d2 < 0) || (d3 < 0);
bool hasPos = (d1 > 0) || (d2 > 0) || (d3 > 0);
return !(hasNeg && hasPos);
}
// Optimized: Project point onto line segment
inline void projectOntoSegment(double px, double py,
double ax, double ay, double bx, double by,
double& outX, double& outY) {
double dx = bx - ax;
double dy = by - ay;
double lengthSq = dx * dx + dy * dy;
if (lengthSq < 0.001) {
outX = ax;
outY = ay;
return;
}
double t = ((px - ax) * dx + (py - ay) * dy) / lengthSq;
t = std::max(0.0, std::min(1.0, t));
outX = ax + t * dx;
outY = ay + t * dy;
}
// Optimized: Clamp to triangle boundary
inline void clampToTriangle(double px, double py, double& outX, double& outY) {
if (isInsideTriangle(px, py)) {
outX = px;
outY = py;
return;
}
// Project onto all three edges
double proj1X, proj1Y, proj2X, proj2Y, proj3X, proj3Y;
projectOntoSegment(px, py, topX, topY, leftX, leftY, proj1X, proj1Y);
projectOntoSegment(px, py, leftX, leftY, rightX, rightY, proj2X, proj2Y);
projectOntoSegment(px, py, rightX, rightY, topX, topY, proj3X, proj3Y);
// Find closest projection
double d1 = distanceSq(px, py, proj1X, proj1Y);
double d2 = distanceSq(px, py, proj2X, proj2Y);
double d3 = distanceSq(px, py, proj3X, proj3Y);
if (d1 <= d2 && d1 <= d3) {
outX = proj1X;
outY = proj1Y;
} else if (d2 <= d3) {
outX = proj2X;
outY = proj2Y;
} else {
outX = proj3X;
outY = proj3Y;
}
}
// Optimized: Convert cartesian to barycentric
inline void cartesianToBary(double px, double py, BarycentricCoord& result) {
// Clamp first
double clampedX, clampedY;
clampToTriangle(px, py, clampedX, clampedY);
// Calculate barycentric coordinates using pre-calculated inverse area
double perf = signedArea(clampedX, clampedY, leftX, leftY, rightX, rightY) * invTotalArea;
double vel = signedArea(clampedX, clampedY, rightX, rightY, topX, topY) * invTotalArea;
double adapt = signedArea(clampedX, clampedY, topX, topY, leftX, leftY) * invTotalArea;
result.performance = std::max(0.0, std::min(1.0, perf));
result.velocity = std::max(0.0, std::min(1.0, vel));
result.adaptability = std::max(0.0, std::min(1.0, adapt));
}
extern "C" {
EMSCRIPTEN_KEEPALIVE
void init() {
const int width = 700;
const int height = 550;
const int padding = 80;
topX = width / 2.0;
topY = padding;
leftX = padding;
leftY = height - padding;
rightX = width - padding;
rightY = height - padding;
// Pre-calculate inverse of total area for optimization
double totalArea = signedArea(topX, topY, leftX, leftY, rightX, rightY);
invTotalArea = (std::abs(totalArea) < 0.001) ? 1.0 : (1.0 / totalArea);
dotPositionDirty = true;
}
EMSCRIPTEN_KEEPALIVE
void handleMouseDown(double mouseX, double mouseY) {
updateDotCartesian();
double distSq = distanceSq(mouseX, mouseY, cachedDotX, cachedDotY);
// If clicking on dot or inside triangle, start dragging
if (distSq < 225) { // 15^2 = 225
isDragging = true;
} else if (isInsideTriangle(mouseX, mouseY)) {
cartesianToBary(mouseX, mouseY, dotPosition);
dotPositionDirty = true;
isDragging = true;
}
}
EMSCRIPTEN_KEEPALIVE
void handleMouseMove(double mouseX, double mouseY) {
if (!isDragging) return;
cartesianToBary(mouseX, mouseY, dotPosition);
dotPositionDirty = true;
}
EMSCRIPTEN_KEEPALIVE
void handleMouseUp() {
isDragging = false;
}
EMSCRIPTEN_KEEPALIVE
double getDotX() {
updateDotCartesian();
return cachedDotX;
}
EMSCRIPTEN_KEEPALIVE
double getDotY() {
updateDotCartesian();
return cachedDotY;
}
EMSCRIPTEN_KEEPALIVE
double getTriangleTopX() { return topX; }
EMSCRIPTEN_KEEPALIVE
double getTriangleTopY() { return topY; }
EMSCRIPTEN_KEEPALIVE
double getTriangleLeftX() { return leftX; }
EMSCRIPTEN_KEEPALIVE
double getTriangleLeftY() { return leftY; }
EMSCRIPTEN_KEEPALIVE
double getTriangleRightX() { return rightX; }
EMSCRIPTEN_KEEPALIVE
double getTriangleRightY() { return rightY; }
EMSCRIPTEN_KEEPALIVE
double getPerformance() { return dotPosition.performance; }
EMSCRIPTEN_KEEPALIVE
double getVelocity() { return dotPosition.velocity; }
EMSCRIPTEN_KEEPALIVE
double getAdaptability() { return dotPosition.adaptability; }
}
// emcc optimization_triangle.cpp -o optimization_triangle.js -O3 -s WASM=1 -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' -s ALLOW_MEMORY_GROWTH=1