如何在 d3 v4 中用点数组绘制圆弧

VIP*_*WAM 2 javascript svg d3.js

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

var points = [
    [
        51.93326250000001,
        21.4375
    ],
    [
        36.72733749999999,
        40.603550000000002
    ],
    [
        21.527537500000008,
        21.4144
    ]
];
Run Code Online (Sandbox Code Playgroud)

我尝试使用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));
Run Code Online (Sandbox Code Playgroud)

但它正在画一条曲线:

在此输入图像描述

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

在此输入图像描述

我不明白如何使用这个:

var arc = d3.arc()
    .innerRadius(180)
    .outerRadius(240)
    .startAngle(0);
Run Code Online (Sandbox Code Playgroud)

与我的观点。

Xav*_*hot 6

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

在这种情况下,由于您的圆弧(圆的一部分)是由 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");
Run Code Online (Sandbox Code Playgroud)
<svg></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
Run Code Online (Sandbox Code Playgroud)


关于数学:

您可以使用任何方法来计算由 3 个点定义的圆的中心。这里用的就是这个

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

您还需要根据第一个点与圆心之间的角度以及最后一个点与圆心之间的角度来了解圆弧的起始角度和结束角度。这可以使用这个公式来实现。


关于绘图:

以下是如何使用 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] + ")");
Run Code Online (Sandbox Code Playgroud)

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

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

.attr("transform", "translate(" + center[0] + "," + center[1] + ")");
Run Code Online (Sandbox Code Playgroud)

我们这样指定圆弧的起始角度和结束角度:

.attr("d", arc({ "startAngle": startAngle, "endAngle": endAngle }))
Run Code Online (Sandbox Code Playgroud)

其中 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;
Run Code Online (Sandbox Code Playgroud)