像素绘画方法(如@Loadmaster 所建议的)在许多方面都优于数学解决方案:
- 实现要简单得多。上述问题只需不到 100 行代码即可解决,as this JSFiddle solution demonstrates(主要是因为它在概念上要简单得多,并且没有需要处理的边缘情况或异常)。
- 它很容易适应更普遍的问题。它适用于任何形状,无论形态如何,只要它可以使用 2D 绘图库(即“全部!”)进行渲染——圆形、椭圆、样条线、多边形,应有尽有。哎呀,甚至位图图像。
- 像素绘画解决方案的复杂度为 ~O[n],而数学解决方案的复杂度为 ~O[n*n]。这意味着随着形状数量的增加,它的性能会更好。
- 说到性能,您通常会免费获得硬件加速,因为大多数现代 2D 库(我相信像 HTML5 的画布)会将渲染工作交给图形加速器。
像素绘制的一个缺点是解决方案的准确性有限。但这可以通过根据情况需要简单地渲染到更大或更小的画布来进行调整。还要注意,2D 渲染代码中的anti-aliasing(通常默认打开)将产生比像素级更好的精度。因此,例如,将 100x100 的图形渲染到相同尺寸的画布上,我认为应该会产生大约 1 / (100 x 100 x 255) = .000039% 的精度……这可能“足够好”除了最苛刻的问题之外的所有问题。
<p>Area computation of arbitrary figures as done thru pixel-painting, in which a complex shape is drawn into an HTML5 canvas and the area determined by comparing the number of white pixels found in the resulting bitmap. See javascript source for details.</p>
<canvas id="canvas" width="80" height="100"></canvas>
<p>Area = <span id="result"></span></p>
// Get HTML canvas element (and context) to draw into
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// Lil' circle drawing utility
function circle(x,y,r) {
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI*2);
ctx.fill();
}
// Clear canvas (to black)
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Fill shape (in white)
ctx.fillStyle = 'white';
circle(40, 50, 40);
circle(40, 10, 10);
circle(25, 15, 12);
circle(35, 90, 10);
// Get bitmap data
var id = ctx.getImageData(0, 0, canvas.width, canvas.height);
var pixels = id.data; // Flat array of RGBA bytes
// Determine area by counting the white pixels
for (var i = 0, area = 0; i < pixels.length; i += 4) {
area += pixels[i]; // Red channel (same as green and blue channels)
}
// Normalize by the max white value of 255
area /= 255;
// Output result
document.getElementById('result').innerHTML = area.toFixed(2);