0

これは最終的に幾何学の問題です。raphaeljs を使用して、一連のデータの各項目に対して 3 つの領域円を描画しています。各円は、カテゴリ内のアイテムの数を表します。

円は接触するが重ならないようにしたいと思います。また、セット全体を親 div の中央に配置したいと考えています。

図はこちら: http://chriscanipe.com/images/circles.jpg

各円の半径と親 div の幅と高さだけがわかれば、各円の中心の xy 座標を計算するにはどうすればよいでしょうか? 考えれば考えるほど、実際には、各コーナーが円の x、y 中心である三角形を描こうとしているように思えます。

4

3 に答える 3

1

これは、アポロニウスの円の問題と呼ばれます。リンクを使用して解決策を見つけることができます。

私はこれの反復的な一般化に取り組んできました。互いに接する 2 つの曲線 A と B が与えられた場合、3 番目の曲線 C を変換して、他の 2 つの曲線に接するようにします。ユーザーは、2 つの固定曲線上のポイント選択の形でいくつかのヒントを提供します。アルゴリズムは次のように進みます。

  1. p と q を、A と B に投影された選択した点とします。
  2. p と q に付随するように C を変換します。
  3. C が p と q で A と B に接するとは思わないので、p と q の新しい選択を見つける必要があります。
  4. これらの点で交わる曲線について、p と q で接触円 (または曲率が 0 の線) を計算します。
  5. 円 (および線分) 間の交点の弦を計算します。
  6. A と B への弦の中点の射影として p と q を取り、交点の弦が十分に小さくなるまで、2 から繰り返します。

もちろん細かい部分はたくさんありますが、このアルゴリズムを実装できる人なら誰でも解決できるはずです。

すぐにイラストを追加しますが、現時点では Mathematica にアクセスできません。

于 2012-06-09T17:49:09.400 に答える
0

これが、この問題に対する私の解決策の実装です。多くのジオメトリとトリガー ID が組み込まれていますが、トリガー関数の呼び出しはありません。

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 <<<    
于 2013-03-13T03:05:21.803 に答える