4

結果セット内の特定の要素の存在に基づいて、3 つの異なるサイズの円で表されるグラフがあります。最初の円は常に 100% に設定されます。これは円が可能な最大のものであり、他の 2 つは最大のものに対する相対 % です。

問題は、css を使用してそれらをレンダリングしようとしていて、それらをすべて側面に沿って「くっつける」方法を理解するために必要な数学がわからないことです。

既知の部分が各円の半径になり、最大の部分が常に最初に返されます。

これが私が達成しようとしているものの例です:

ここに画像の説明を入力

このように配置する margin-top と margin-left を各円に提供できるように、これを数学的に達成するにはどうすればよいですか?

最大の円を 0,0 に配置し、2 番目に大きい円を 2 つの直径の差の半分に配置して、中心点を揃えます。本当の課題は、3 番目に小さい円で、他の 2 つの円の位置に基づいて配置する場所を知ることです。

4

4 に答える 4

5

辺が radius0、radius1、radius2 の三角形を作成し、3 番目の頂点座標 (最小の円の中心) を計算します。ここから計算式 (23) を使用しました。Delphi コードがありますが、原則が明確であることを願っています。

var
  r0, r1, r2: Integer;
  x0, x1, x2, y0, y1, y2: Integer;
  a, b, c, ca: Double;
begin
  //some intialization
  Canvas.FillRect(ClientRect);
  Randomize;
  r0 := 200;
  r1 := Round(r0 * (0.25 + 0.75 * Random));
  r2 := Round(r1 * (0.25 + 0.75 * Random));

  //circle centers' coordinates
  //biggest
  x0 := r0;
  y0 := r0;

  //second
  x1 := x0 + r0 + r1;
  y1 := y0;

  //triangle sides
  c := r0 + r1;
  b := r0 + r2;
  a := r1 + r2;

  //x-shift
  ca := (c * c + b * b - a * a) / (2.0 * c);
  x2 := x0 + Round(ca);

  //y-shift is the height of triangle
  //Pythagor's rule
  y2 := y0 + Round(Sqrt(b * b - ca * ca));

  //draw calculated circles
  Canvas.Ellipse(x0 - r0, y0 - r0, x0 + r0 + 1, y0 + r0 + 1);
  Canvas.Ellipse(x1 - r1, y1 - r1, x1 + r1 + 1, y1 + r1 + 1);
  Canvas.Ellipse(x2 - r2, y2 - r2, x2 + r2 + 1, y2 + r2 + 1);

出力例: ここに画像の説明を入力

于 2013-01-29T04:09:19.743 に答える
3

わかりました、それぞれを見ていきましょう... 100% A 円の半径が x であると仮定しましょう (例として、B は Bx で、c は Cx で、B = .7 と C = .3 です)。

別のこととして、私は実際に a<div style="position: relative"></div>を持っていて、あなたの円は<div style="position: absolute, top: 0, left: 0"></div>margin-top/margin-left を使用する代わりに

いずれかの方法。明らかに、上/左 = 0 になります。

あなたの写真から、AとBの中心が並んでいるように見えます...これは、Bが持つことを意味しleft = 2xますtop = (1 - B)x

Cは難しい部分です...参照用に簡単なペイントトライアングルをアップします

まず、コサインの法則を使用して、A の角度を見つけます。

(B + C)² = (1 + B)² + (1 + C)² - 2(1 + B)(1 + C)cos A

cosA = (BC - B - C - 1)/(BC + B + C + 1)

通常の三角法を使用して、高さを取得することもできます...

sin A = h / (1 + C)

ルールの使用

sin² A + cos² A = 1

組み合わせて手に入れることができます

h = (1 + C) √ (1 - cos² A)

もちろん、トップを取得するには、1 を足して C を引く必要があります。

top = ((1 + C) √ (1 - cos² A) + 1 - C)x

もう一度三角関数を使用すると、左側を取得できます...

cos A = l / (1 + C)

l = (1 + C)cos A

もちろん、左に移動するには、1 を足して C を取らなければなりません...

left = ((1 + C)cos A + 1 - C)x

B = .7、C = .3、x = 50px の円を作成するために、border-radius を使用して例を作成しました: http://jsfiddle.net/FelixJorkowski/xArpR/

于 2013-01-29T04:40:20.893 に答える
0

これが@MBoのコードのPython実装です

r0 = 100
r1 = 50
r2 = 25

#circles
#biggest
x0 = r0
y0 = r0

#2位
x1 = x0 + r0 + r1
y1 = y0

#sides
c = r0 + r1
b = r0 + r2
a = r1 + r2

#x-shift
ca =(c * c + b * b --a * a)/(2.0 * c)
x2 = x0 + round(ca)

#y-shiftは三角形の高さです
y2 = y0 + round(math.sqrt(b * b --ca * ca))

left_a = x0-r0
top_a = y0-r0
width_a = r0 * 2
border_radius_a = width_a / 2

left_b = x1-r1
top_b = y1-r1
width_b = r1 * 2
border_radius_b = width_b / 2

left_c = x2-r2
top_c = y2-r2
width_c = r2 * 2
border_radius_c = width_c / 2
于 2013-01-29T16:38:21.543 に答える
0

他の人がこれに遭遇した場合に備えて、キャンバス要素を使用したソリューション。

http://jsfiddle.net/5mgLY/

var centerpoint = 50;
var radius = randomFromInterval(30, 50);                //starting circle between 30 and 50
var radius2 = radius * randomFromInterval(5, 9) / 10;   //between .5 and .9 of starting circle
var radius3 = radius2 * randomFromInterval(3, 8) / 10;  //between .3 and .8 of medium circle

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

//draw the big circle
ctx.beginPath();
ctx.arc(centerpoint,centerpoint,radius,0,2*Math.PI,false);
ctx.fillStyle = 'green';
ctx.fill();
ctx.stroke();

//draw the medium circle
ctx.beginPath();
ctx.arc(centerpoint + radius + radius2,50,radius2,0,2*Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
ctx.stroke();

//find the length of each side of the triangle that forms between the three circles
var hypotenuse = radius + radius2;
var side1 = radius + radius3;
var side2 = radius2 + radius3;

//get x and y offsets
var xOffset = ((hypotenuse*hypotenuse) + (side1*side1)  - (side2*side2)) / (2 * hypotenuse);
var yOffset = Math.sqrt(side1 * side1 - xOffset * xOffset);

//draw the small circle
ctx.beginPath();
ctx.arc(centerpoint + xOffset,centerpoint + yOffset,radius3,0,2*Math.PI);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.stroke();

function randomFromInterval(from,to)
{
    return Math.floor(Math.random()*(to-from+1)+from);
}

function toDegrees (angle) {
  return angle * (180 / Math.PI);
}
于 2013-01-30T05:04:14.883 に答える