Piksel boyama yaklaşımı (@Loadmaster tarafından önerildiği üzere) matematiksel çözümden çeşitli şekillerde üstündür:
- Uygulama çok daha basittir. Yukarıdaki sorun, bu JSFiddle çözümünün gösterdiği gibi (çoğunlukla kavramsal olarak daha basit olduğu ve başa çıkılması gereken uç durumlar veya istisnalar olmadığı için) 100 satırdan daha az kodla çözülebilir .
- Daha genel sorunlara kolayca uyum sağlar. 2B çizim kitaplıkları (yani "hepsi") - daireler, elipsler, spline'lar, poligonlar, siz adlandırın, morfolojiden bağımsız olarak herhangi bir şekilde çalışır. Heck, hatta bitmap görüntüleri.
- Matematiksel çözüm için ~ O [n * n] ile karşılaştırıldığında piksel boyama çözümünün karmaşıklığı ~ O [n] 'dir. Bu, şekil sayısı arttıkça daha iyi performans göstereceği anlamına gelir.
- Ve performanstan bahsetmişken, çoğu modern 2D kitaplığı (HTML5'in tuvali gibi) oluşturma işini grafik hızlandırıcılara yükleyeceğine inanıyorum.
Piksel boyamanın bir dezavantajı, çözümün sınırlı doğruluğu. Ancak bu, durumun gerektirdiği şekilde daha büyük veya daha küçük tuvallere dönüştürülerek ayarlanabilir. Not, o da anti-aliasing kodu render 2D (genellikle varsayılan olarak açık) daha iyi-daha-piksel seviyesinde verecektir doğruluğu. Bu nedenle, örneğin, 100x100'lük bir figürü aynı boyutlarda bir tuvalde işlemek, sanırım 1 / (100 x 100 x 255) = .000039% düzeyinde doğruluk sağlamalı ... ki bu muhtemelen "yeterince iyi" en zorlu sorunlar hariç hepsi için.
<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);