วิธีการวาดภาพพิกเซล (ตามที่แนะนำโดย @Loadmaster) ดีกว่าวิธีการแก้ปัญหาทางคณิตศาสตร์ในหลาย ๆ วิธี:
- การดำเนินการเป็นมากง่าย ปัญหาข้างต้นสามารถแก้ไขได้ในโค้ดน้อยกว่า 100 บรรทัดเนื่องจากโซลูชัน JSFiddle นี้แสดงให้เห็น (ส่วนใหญ่เป็นเพราะแนวคิดนั้นง่ายกว่ามากและไม่มีกรณีขอบหรือข้อยกเว้นในการจัดการ)
- มันปรับให้เข้ากับปัญหาทั่วไปได้ง่ายขึ้น มันใช้งานได้กับรูปร่างใด ๆ โดยไม่คำนึงถึงสัณฐานวิทยาตราบใดที่สามารถแสดงผลได้ด้วยไลบรารีการวาดภาพ 2 มิติ (กล่าวคือ“ ทั้งหมด!”) - วงกลมวงรีเส้นโค้งรูปหลายเหลี่ยมคุณตั้งชื่อมัน Heck แม้กระทั่งภาพบิตแมป
- ความซับซ้อนของวิธีการวาดภาพพิกเซลคือ ~ O [n] เมื่อเทียบกับ ~ O [n * n] สำหรับวิธีการแก้ปัญหาทางคณิตศาสตร์ ซึ่งหมายความว่าจะทำงานได้ดีขึ้นเมื่อจำนวนรูปร่างเพิ่มขึ้น
- และเมื่อพูดถึงประสิทธิภาพคุณมักจะได้รับการเร่งด้วยฮาร์ดแวร์ฟรีเนื่องจากไลบรารี 2D ที่ทันสมัยที่สุด (เช่นผืนผ้าใบของ HTML5 ฉันเชื่อว่า) จะกำจัดการแสดงผลงานไปยังตัวเร่งกราฟิก
ข้อเสียอย่างหนึ่งของการวาดภาพด้วยพิกเซลคือความแม่นยำที่ จำกัด ของโซลูชัน แต่สามารถปรับแต่งได้โดยการแสดงผลเป็นผืนผ้าใบที่ใหญ่ขึ้นหรือเล็กลงตามที่สถานการณ์ต้องการ โปรดทราบด้วยว่าการลบรอยหยักในโค้ดการแสดงผล 2 มิติ (มักจะเปิดใช้งานโดยค่าเริ่มต้น) จะให้ความแม่นยำที่ดีกว่าระดับพิกเซล ตัวอย่างเช่นฉันคิดว่าการเรนเดอร์ตัวเลข 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);