2012-06-09 23 views
0

這最終是一個幾何問題。我使用raphaeljs爲一系列數據中的每個項目繪製3個區域圓圈。每個圓圈表示一個類別中的項目數量。根據它們的半徑計算三個接觸圓的位置

我想圈子觸摸但不重疊,我想整個集中在其父div的中間。

圖這裏:http://chriscanipe.com/images/circles.jpg

只知道每個圓圈和父div的寬度和高度的半徑,我將如何去計算的XY座標是每個圓的中心?我越想到它,我想我其實正在畫一個三角形,其中每個角落是一個圓圈的x,y中心。

+0

你能用圖像更新問題嗎?鏈接已經死亡。 –

回答

1

您有許多限制條件,您需要在上面限制或選擇限制或超出最初的問題。在您的示例圖像中,您是如何決定旋轉中心形成的三角形的?你叫什麼三角形的「中心」?接近這個

一種方式可能是:

假設在原點(0,0) 第一圓假設在正上方這一個點的第二圓(0,R1 + R2) 計算第三點 - 這是兩個圓的交集。一個以原點爲中心,半徑爲r1 + r3,另一個以(0,r1 + r2)爲中心,半徑爲r2 + r3。

現在你就可以計算出一個「中心」

然後你就可以得出基於該中心和您的div的尺寸你的圈子這三點。

1

這被稱爲Circles of Apollonius的問題。您可以使用鏈接找到解決方案。

我一直在對此進行迭代推廣。給定兩條曲線A和B彼此相切的曲線,轉換第三條曲線C,使其與另外兩條曲線相切。用戶在兩條固定曲線上以點選形式提供一些提示。該算法如下進行:

  1. 設p和q是投影到A和B.
  2. 所選擇的點變換C++,使得其入射到p和q。
  3. 由於我們不希望C在p和q上與A和B相切,我們需要找到p和q的新選擇。
  4. 在p和q處計算在這些點相交的曲線的計算密切圓(或曲率爲0的直線)。
  5. 計算圓(和線)之間的交點的和絃。
  6. 將p和q作爲和絃中點到A和B上的投影,並從2開始重複,直到交點的和絃足夠小。

當然有很多黑鬼的細節,但任何能夠實現這個算法的人都應該能夠解決這些問題。

我會盡快添加一個插圖,但目前我無法訪問Mathematica。

0

這是我對這個問題的解決方案的實現。 它包含了很多幾何和觸發標識 - 但沒有調用觸發函數。

HTML >>> 
<!DOCTYPE HTML> 
<html> 
    <head> 
    <title> 
     Tangent Circles in a Box 
    </title> 
    <link rel="stylesheet" href="CSS/tangent_circles.css" type="text/css" /> 
    </head> 
    <body> 
    <div id="main_container"> 
     <div id="inner_container"> 
     <img class="circle" id="left_circle" src="http://www.clker.com/cliparts/Z/Z/S/Y/S/w/red-circle-cross-transparent-background-md.png" alt="left_circle" /> 
     <img class="circle" id="right_circle" src="http://www.clker.com/cliparts/Z/Z/S/Y/S/w/red-circle-cross-transparent-background-md.png" alt="right_circle" /> 
     <img class="circle" id="third_circle" src="http://www.clker.com/cliparts/Z/Z/S/Y/S/w/red-circle-cross-transparent-background-md.png" alt="third_circle" /> 
     </div> 
    </div> 
    <div id="userControls"> 
     <form id="userControlsForm"> 
     Circle One <input id="circleOneInput" type="text" placeholder="Enter Numeric Value" value=""><br> 
     Circle Two <input id="circleTwoInput" type="text" placeholder="Enter Numeric Value" value=""><br> 
     Circle Three <input id="circleThreeInput" type="text" placeholder="Enter Numeric Value" value=""> 
     <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script> 
     <script src="JS/tangent_circles.js"></script> 
     </form> 
    </div> 
    </body> 
</html> 
HTML <<< 

CSS >>> 
body 
{ 
    background-color: white; 
} 

#main_container 
{ 
    background-color: #cccccc; 
    width: 800px; 
    height: 800px; 
    margin: auto; 
    border: solid #cccccc 1px; 
    -o-border-radius: 4px; 
    -moz-border-radius: 4px; 
    -webkit-border-radius: 4px; 
    border-radius: 4px; 
} 

    #inner_container 
    {  
    width: 100%; 
    height: 100%; 
    position: relative; 
    } 

    .circle 
    { 
     position: absolute; 
     text-align: center; 
     font-family: fantasy; 
    } 
     #left_circle 
    { 
     top: 0px; 
     left: 0px; 
     width: 300px; 
     height: 300px; 
    } 

    #right_circle 
    { 
     top: 0px; 
     left: 0px; 
     width: 300px; 
     height: 300px; 
    } 

    #third_circle 
    { 
     top: 0px; 
     left: 0px; 
     width: 300px; 
     height: 300px; 
    } 

    #userControls 
    { 
     padding: 30px; 
     width: 400px; 
     height: 200px; 
     margin: auto; 
     margin-top: 30px; 
     background-color: #dddddd; 
    } 

     #circleOneInput 
     { 
     margin-bottom: 10px; 
     } 

     #circleTwoInput 
     { 
     margin-bottom: 10px; 
     } 

#userControls 
{ 
    position: absolute; 
    left : 20px; 
    top  : 50px; 
    width : 200px; 
} 
CSS <<< 
JS >>> 
$(function() { 
    function changeCircles(){ 
    $("#inputWarning").remove(); 
    var radius1 = parseInt($("#circleOneInput").val(), 10); 
    var radius2 = parseInt($("#circleTwoInput").val(), 10); 
    var radius3 = parseInt($("#circleThreeInput").val(), 10); 
    console.log('radius1 = ' + radius1 + ', ' + 
       'radius2 = ' + radius2 + ', ' + 
       'radius3 = ' + radius3 
    ); 
    if (isNaN(radius1) || isNaN(radius2) || isNaN(radius3)) 
    { 
     $("#userControlsForm").after('<span id="inputWarning" style="color: red;">Only Numbers Please</span>'); 
    } 
    else 
    { 
     // normalize circle sizes 

     if (radius1 < 10) 
     { 
     radius1 = 10; 
     } 

     if (radius2 < 10) 
     { 
     radius2 = 10; 
     } 

     if (radius3 < 10) 
     { 
     radius3 = 10; 
     } 

     if (radius1 > 150) 
     { 
     radius1 = 150; 
     } 

     if (radius2 > 150) 
     { 
     radius2 = 150; 
     } 

     if (radius3 > 150) 
     { 
     radius3 = 150; 
     } 

     // do the actual circle changing 
     // 1) calculate 
     // 2) animate 
     // calculate sides of triangle 
     var a = radius2 + radius3; 
     var b = radius1 + radius3; 
     var c = radius2 + radius1; 

     // get dimensions of containing div 
     var container_width = $("#inner_container").width(); 
     var container_height = $("#inner_container").height(); 

     var center_x = container_width/2.0; 
     var center_y = container_height/2.0; 

     // calculate cosine and sine of angle inside circle b 
     var cos_beta = ((a * a) + (c * c) - (b * b))/(2 * a * c); 
     var sin_beta = Math.sqrt(1 - cos_beta * cos_beta); 

     // calculate coordinates of circles a and b 
     var Ax = 0; 
     var Ay = 0; 
     var Bx = radius1 + radius2; 
     var By = 0; 

     // calculate cosine and sine of angle between triangle and horizontal 
     var cos_phi = (Bx - Ax)/c; 
     var sin_phi = Math.sqrt(1 - cos_phi * cos_phi); 

     // calculate the cosine and sine of the sum of both angles 
     var cos_phiNbeta = cos_phi * cos_beta - sin_beta * sin_phi; 
     var sin_phiNbeta = cos_phi * sin_beta + sin_phi * cos_beta; 

     // calculate coordinates of circle c 
     var Cx = Bx - cos_phiNbeta * a; 
     var Cy = By + sin_phiNbeta * a; 

     // find centroid 
     var centroid_x = (Ax + Bx + Cx)/3.0; 
     var centroid_y = (Ay + By + Cy)/3.0; 

     // get coordinate adjustment 
     var adjust_x = center_x - centroid_x; 
     var adjust_y = center_y - centroid_y; 

     // convert coordinates to div position values 
     var A_left = Ax + adjust_x - radius1; 
     var A_top = Ay + adjust_y - radius1; 
     var B_left = Bx + adjust_x - radius2; 
     var B_top = By + adjust_y - radius2; 
     var C_left = Cx + adjust_x - radius3; 
     var C_top = Cy + adjust_y - radius3; 

     // calculate div dimensions 
     var A_width = 2 * radius1; 
     var A_height = 2 * radius1; 
     var B_width = 2 * radius2; 
     var B_height = 2 * radius2; 
     var C_width = 2 * radius3; 
     var C_height = 2 * radius3; 

    // the following needs Jquery 
     var circle_a = $("#left_circle"); 
     var circle_b = $("#right_circle"); 
     var circle_c = $("#third_circle"); 

     circle_a.animate({ 
         'top' : A_top + 'px', 
         'left' : A_left + 'px', 
         'width' : A_width + 'px', 
         'height': A_height + 'px' 
         }, 500); 

     circle_b.animate({ 
         'top' : B_top + 'px', 
         'left' : B_left + 'px', 
         'width' : B_width + 'px', 
         'height': B_height + 'px' 
         }, 500); 


     circle_c.animate({ 
         'top' : C_top + 'px', 
         'left' : C_left + 'px', 
         'width' : C_width + 'px', 
         'height': C_height + 'px' 
         }, 500); 


    } 
    } 
    $("#circleOneInput").keyup(changeCircles); 
    $("#circleTwoInput").keyup(changeCircles); 
    $("#circleThreeInput").keyup(changeCircles); 
}); // end ready 
JS <<<