给定一个圆心为(200,200),半径为25的圆,如何画出一条从270度到135度的弧以及一条从270度到45度的弧?

0度表示它在x轴上(右侧)(表示它是3点钟位置) 270度表示12点钟位置,90度表示6点钟位置

更一般地说,弧的路径是圆的一部分

x, y, r, d1, d2, direction

意义

center (x,y), radius r, degree_start, degree_end, direction

当前回答

基于所选答案的ReactJS组件:

import React from 'react';

const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
    const angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0;

    return {
        x: centerX + (radius * Math.cos(angleInRadians)),
        y: centerY + (radius * Math.sin(angleInRadians))
    };
};

const describeSlice = (x, y, radius, startAngle, endAngle) => {

    const start = polarToCartesian(x, y, radius, endAngle);
    const end = polarToCartesian(x, y, radius, startAngle);

    const largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";

    const d = [
        "M", 0, 0, start.x, start.y,
        "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
    ].join(" ");

    return d;
};

const path = (degrees = 90, radius = 10) => {
    return describeSlice(0, 0, radius, 0, degrees) + 'Z';
};

export const Arc = (props) => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
    <g transform="translate(150,150)" stroke="#000" strokeWidth="2">
        <path d={path(props.degrees, props.radius)} fill="#333"/>
    </g>

</svg>;

export default Arc;

其他回答

我会使用其他答案的代码,它们看起来都是互相复制的,但是我会让起点是开始角度的函数而终点是结束角度的函数。

我将使用绝对值使大圆弧标志与顺序无关,并通过360度模数使角度与数值大小无关。

var start = polarToCartesian(x, y, radius, startAngle);
var end = polarToCartesian(x, y, radius,   endAngle);

largeArcFlag = Math.abs((endAngle - startAngle) % 360) <= 180 ? "0" : "1";
clockwiseFlag = (endAngle > startAngle) ? "1" : "0";

var d = [
    "M", start.x, start.y, 
    "A", radius, radius, 0, largeArcFlag, clockwiseFlag, end.x, end.y
  ].join(" ");

向威利道歉;我还没读到最后,他也发现了同样的事情。如果你喜欢我的帖子,就给他投票吧!

一个图像和一些Python

只是为了更好地澄清并提供另一种解决方案。Arc [A]命令使用当前位置作为起点,因此您必须先使用Moveto [M]命令。

那么Arc的参数如下:

rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, xf, yf

如果我们定义下面的svg文件:

<svg viewBox="0 0 500px 500px"> <path fill="red" d=" M 100 100 A 40 40 00 0 180 100 Z " / > < / svg >

你可以用M来设定起点,用参数xf和yf (A)来设定终点。

我们正在寻找圆,所以我们设rx = ry现在基本上它会尝试找到所有半径为rx的圆相交于起点和终点。

import numpy as np

def write_svgarc(xcenter,ycenter,r,startangle,endangle,output='arc.svg'):
    if startangle > endangle: 
        raise ValueError("startangle must be smaller than endangle")
    
    if endangle - startangle < 360:
        large_arc_flag = 0
        radiansconversion = np.pi/180.
        xstartpoint = xcenter + r*np.cos(startangle*radiansconversion)
        ystartpoint = ycenter - r*np.sin(startangle*radiansconversion)
        xendpoint = xcenter + r*np.cos(endangle*radiansconversion)
        yendpoint = ycenter - r*np.sin(endangle*radiansconversion)
        #If we want to plot angles larger than 180 degrees we need this
        if endangle - startangle > 180: large_arc_flag = 1
        with open(output,'a') as f:
            f.write(r"""<path d=" """)
            f.write("M %s %s" %(xstartpoint,ystartpoint))
            f.write("A %s %s 0 %s 0 %s %s" 
                    %(r,r,large_arc_flag,xendpoint,yendpoint))
            f.write("L %s %s" %(xcenter,ycenter))
            f.write(r"""Z"/>""" )
    
    else:
        with open(output,'a') as f:
            f.write(r"""<circle cx="%s" cy="%s" r="%s"/>"""
                    %(xcenter,ycenter,r))

你可以在我写的这篇文章中有更详细的解释。

您需要使用椭圆Arc命令。不幸的是,这需要指定起始点和结束点的笛卡尔坐标(x, y),而不是现有的极坐标(半径,角度),因此必须进行一些数学计算。下面是一个可以工作的JavaScript函数(虽然我还没有测试它),我希望它是相当不言自明的:

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
  var angleInRadians = angleInDegrees * Math.PI / 180.0;
  var x = centerX + radius * Math.cos(angleInRadians);
  var y = centerY + radius * Math.sin(angleInRadians);
  return [x,y];
}

哪些角度对应哪些时钟位置将取决于坐标系;只需要交换sin/cos项。

arc命令有以下参数:

rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y

第一个例子:

rx=ry=25 and x-axis-rotation=0, since you want a circle and not an ellipse. You can compute both the starting coordinates (which you should Move to) and ending coordinates (x, y) using the function above, yielding (200, 175) and about (182.322, 217.678), respectively. Given these constraints so far, there are actually four arcs that could be drawn, so the two flags select one of them. I'm guessing you probably want to draw a small arc (meaning large-arc-flag=0), in the direction of decreasing angle (meaning sweep-flag=0). All together, the SVG path is:

M 200 175 A 25 25 0 0 0 182.322 217.678

对于第二个例子(假设您的意思是走向相同的方向,因此是一个大的弧),SVG路径是:

M 200 175 A 25 25 0 1 0 217.678 217.678

同样,我还没有测试这些。

如果你像@clocksmith一样,想知道他们为什么选择这个API,看看实现说明。他们描述了两种可能的弧参数化,“端点参数化”(他们选择的那个)和“中心参数化”(就像这个问题使用的那样)。在“端点参数化”的描述中,他们说:

端点参数化的优点之一是它允许一致的路径语法,其中所有路径命令都以新的“当前点”的坐标结束。

所以基本上,这是弧线被视为更大路径的一部分的副作用,而不是它们自己单独的物体。我认为如果您的SVG渲染器是不完整的,它可以跳过任何它不知道如何渲染的路径组件,只要它知道它们接受多少参数。或者它可能支持并行渲染具有多个组件的路径的不同块。或者他们这样做是为了确保舍入误差不会沿着复杂路径的长度累积。

实现说明对于最初的问题也很有用,因为它们有更多用于在两个参数化之间转换的数学伪代码(我第一次写这个答案时没有意识到这一点)。

由wdebeaum得到的原始极坐标笛卡尔函数是正确的:

var angleInRadians = angleInDegrees * Math.PI / 180.0;

使用以下方法反转起始点和结束点:

var start = polarToCartesian(x, y, radius, endAngle);
var end = polarToCartesian(x, y, radius, startAngle);

(对我来说)是混乱的,因为这将反转扫旗。使用:

var start = polarToCartesian(x, y, radius, startAngle);
var end = polarToCartesian(x, y, radius, endAngle);

使用sweep-flag = "0"绘制"正常"逆时针弧线, 我认为这更直接。 参见https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths

@opsb的回答很简洁,但中心点不准确,而且,正如@Jithin指出的那样,如果角度是360,那么什么都画不出来。

@Jithin修复了360度的问题,但如果你选择小于360度,那么你会得到一条线关闭弧环,这是不需要的。

我修复了这个问题,并在下面的代码中添加了一些动画:

function myArc(cx, cy, radius, max){ var circle = document.getElementById("arc"); var e = circle.getAttribute("d"); var d = " M "+ (cx + radius) + " " + cy; var angle=0; window.timer = window.setInterval( function() { var radians= angle * (Math.PI / 180); // convert degree to radians var x = cx + Math.cos(radians) * radius; var y = cy + Math.sin(radians) * radius; d += " L "+x + " " + y; circle.setAttribute("d", d) if(angle==max)window.clearInterval(window.timer); angle++; } ,5) } myArc(110, 110, 100, 360); <svg xmlns="http://www.w3.org/2000/svg" style="width:220; height:220;"> <path d="" id="arc" fill="none" stroke="red" stroke-width="2" /> </svg>