Find all circle intersections on the outer perimeter (e.g. B,D,F,H on the following diagram). Connect them together with the centres of the corresponding circles to form a polygon. The area of the union of the circles is the area of the polygon + the area of the circle slices defined by consecutive intersection points and the circle center in between them. You'll need to also account for any holes.
根据你试图解决的问题,它可能足以得到一个上限和下限。上界很简单,就是所有圆的总和。对于一个下限,你可以选择一个单一的半径,使任何圆重叠。为了更好地找到每个圆的最大半径(直到实际半径) ,这样它就不会重叠。去掉任何完全重叠的圆(所有这些圆都满足 | P _ a-P _ b | < = r _ a) ,其中 P _ a 是圆 A 的中心,P _ b 是圆 B 的中心,而 r _ a 是 A 的半径)也应该是相当琐碎的,这样就更好地得到了上界和下界。如果在任意对上使用配对公式,而不仅仅是所有圆的和,你也可以得到一个更好的上界。可能有一个很好的方法来选择“最佳”对(导致最小总面积的对)。
The pixel-painting approach (as suggested by @Loadmaster) is superior to the mathematical solution in a variety of ways:
Implementation is 很多 simpler. The above problem can be solved in less than 100 lines of code, as this JSFiddle solution demonstrates (mostly because it’s conceptually much simpler, and has no edge cases or exceptions to deal with).
It adapts easily to more general problems. It works with any shape, regardless of morphology, as long as it’s renderable with 2D drawing libraries (i.e., “all of them!”) — circles, ellipses, splines, polygons, you name it. Heck, even bitmap images.
与数学解的复杂度相比,像素绘制解的复杂度为 ~ O [ n ]。这意味着随着形状数量的增加,它将表现得更好。
<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);
Ants Aasma's answer gave the basic idea, but I wanted to make it a little more concrete. Take a look at the five circles below and the way they've been decomposed.
This decomposes the circle union into a set of polygons (shaded blue) and circular pie pieces (shaded green) that are pairwise disjoint and cover the original union (that is, a partition). Since each piece here is something that's easy to compute the area of, you can compute the area of the union by summing the pieces' areas.
这个问题可以用 格林定理解决,复杂度为 n ^ 2log (n)。
如果你对 格林定理不熟悉,想了解更多,这里是来自可汗学院的 视频和 笔记。但为了解决我们的问题,我想我的描述就足够了。
如果我把 L和 M这样
那么 RHS 就是区域 R的面积,可以通过求封闭积分或 LHS 得到,这就是我们要做的。
所以沿逆时针方向积分,得到区域的 地区,沿顺时针方向积分,得到负的 地区。那么
(沿着逆时针方向的红色弧线集成 + 沿着顺时针方向的蓝色弧线集成)
But the cool trick is if for each circle if we integrate the arcs which are not inside any other circle we get our required area i.e. we get integration in an anticlockwise direction along all red arcs and integration along all blue arcs along the clockwise direction. 任务完成! ! !