如何在d3 v4中绘制带有点阵列的圆弧

时间:2018-04-26 18:31:26

标签: javascript d3.js svg

我想从这样的点数组中绘制一个弧:

var points = [
    [
        51.93326250000001,
        21.4375
    ],
    [
        36.72733749999999,
        40.603550000000002
    ],
    [
        21.527537500000008,
        21.4144
    ]
];

我尝试了d3.line()d3.curveBasis()d3.curveBundle.beta(1)

var arcPath = d3.line()
    .x(function (d) {
         return d[0];
    })
    .y(function (d) {
         return d[1];
    })
    .curve(d3.curveBasis);
    var arc = node.append('path').attr("d", arcPath(points));

但它正在绘制一条曲线:

enter image description here

这不是我要找的。我想要一个弧:

enter image description here

我不明白如何使用它:

var arc = d3.arc()
    .innerRadius(180)
    .outerRadius(240)
    .startAngle(0);

以我的观点。

1 个答案:

答案 0 :(得分:3)

为了绘制圆弧,您需要知道其相关圆的中心坐标及其半径。

在这种情况下,当您的弧(圆的一部分)由3个点的坐标定义时,您需要计算由这3个点定义的圆的中心:



var points = [
  [
    51.93326250000001,
    21.4375
  ],
  [
    36.72733749999999,
    40.603550000000002
  ],
  [
    21.527537500000008,
    21.4144
  ]
];

function calculateCircleCenter(A, B, C) {

  var yDelta_a = B[1] - A[1];
  var xDelta_a = B[0] - A[0];
  var yDelta_b = C[1] - B[1];
  var xDelta_b = C[0] - B[0];

  var center = [];

  var aSlope = yDelta_a / xDelta_a;
  var bSlope = yDelta_b / xDelta_b;

  center[0] = (aSlope*bSlope*(A[1] - C[1]) + bSlope*(A[0] + B[0]) - aSlope*(B[0]+C[0]) )/(2* (bSlope-aSlope) );
  center[1] = -1*(center[0] - (A[0]+B[0])/2)/aSlope +  (A[1]+B[1])/2;

  return center;
}

function distance(A, B) {
  var a = A[0] - B[0];
  var b = A[1] - B[1];
  return Math.sqrt(a*a + b*b);
}

var center = calculateCircleCenter(points[0], points[1], points[2]);

var radius = distance(points[0], center);

var svg = d3.select("svg").attr("width", 200).attr("height", 200);

// The circle
svg.append("circle")
  .attr("cx", center[0])
  .attr("cy", center[1])
  .attr("r", radius)
  .attr("fill", "white")
  .attr("stroke", "black");

var startAngle = Math.atan2(points[0][1] - center[1], points[0][0] - center[0]) + 0.5 * Math.PI;
var endAngle = Math.atan2(center[1] - points[2][1], center[0] - points[2][0]) + 1.5 * Math.PI;

var arc = d3.arc().innerRadius(radius).outerRadius(radius);

var sector = svg.append("path")
  .attr("fill", "none")
  .attr("stroke-width", 2)
  .attr("stroke", "blue")
  .attr("d", arc({ "startAngle": startAngle, "endAngle": endAngle }))
  .attr("transform", "translate(" + center[0] + "," + center[1] + ")");

// The 3 points:
svg.selectAll("small_circle")
  .data(points)
  .enter().append("circle")
  .attr("cx", function (d) { return d[0]; })
  .attr("cy", function (d) { return d[1]; })
  .attr("r", 2)
  .attr("fill", "red");

<svg></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;

关于数学:

您可以使用任何方法计算由3个点定义的圆心。此处使用此one

然后,您可以通过计算此中心与三个点之一之间的距离来计算此圆的半径。

您还需要根据第一个点和圆的中心之间的角度以及最后一个点和圆的中心之间的角度来了解弧的起点和终点角度。 。这可以使用此formula来实现。

关于绘图:

以下是使用d3.js绘制弧的方法:

var arc = d3.arc().innerRadius(radius).outerRadius(radius);

var sector = svg.append("path")
 .attr("fill", "none")
 .attr("stroke-width", 2)
 .attr("stroke", "blue")
 .attr("d", arc({ startAngle: 0.5 * Math.PI, endAngle: 1.5 * Math.PI }))
 .attr("transform", "translate(" + center[0] + "," + center[1] + ")");

弧由其半径定义。更具体地说是innerRadiusouterRadius。在我们的例子中,它是一样的。

然后我们通过平移弧来指定弧的中心:

.attr("transform", "translate(" + center[0] + "," + center[1] + ")");

我们用这种方式指定弧的起点和终点角度:

.attr("d", arc({ "startAngle": startAngle, "endAngle": endAngle }))

其中startAngle和endAngle是根据第一个/最后一个点和中心计算的:

var startAngle = Math.atan2(points[0][1] - center[1], points[0][0] - center[0]) + 0.5 * Math.PI;
var endAngle = Math.atan2(center[1] - points[2][1], center[0] - points[2][0]) + 1.5 * Math.PI;