在两条线之间画圆弧。我需要计算点数
Draw arc between two lines. I need to calculate points
我找不到在两条线之间绘制 ARC 的方法。我的约束是:我必须计算这个圆弧笔划点。因为我正在使用 InkCanvas 并且我必须逐点绘制此弧线,所以我无法将任何对象放到屏幕或 canvas 上。所以我知道我可以用 PATH 对象绘制任何弧线并使用 ArcSegment。使用此方法是的,我可以绘制圆弧,但它不是 Canvas 上的笔划点。因此我无法删除或保存它。
不管怎样,我需要逐点计算这个拱门。
我有像这样在 canvas 上画圆的代码:
Stroke GetCircleStroke(int centerX, int centerY, int radiusX, int radiusY,double angletoDraw=2.0)
{
StylusPointCollection strokePoints = new StylusPointCollection();
int numTotalSteps = 180;
for (int i = 0; i <= numTotalSteps; i++)
{
double angle = angletoDraw * Math.PI * (double)i / (double)numTotalSteps;
StylusPoint sp = new StylusPoint();
//compute x and y points
sp.X = centerX + Math.Cos(angle) * radiusX;
sp.Y = centerY - Math.Sin(angle) * radiusY;
//add to the collection
strokePoints.Add(sp);
}
Stroke newStroke = new Stroke(strokePoints);
return newStroke;
}
我可以很容易地画圆,但是我找不到画弧的方法:(
我们知道中心点 X,Y,我们知道 Line1 和 Line2 坐标。就是不知道那个弧线是什么..
你能帮我这样计算圆弧点吗?
你有一些概念飞来飞去,比如 Line
/Segment
、Point
、Circle
等。不要把代码弄得一团糟,让我们试着把问题分解成更容易理解的更小的部分。
你有一个点的概念,好的,让我们实现一个:
public struct Point2D //omitted equality logic
{
public double X { get; }
public double Y { get; }
public Point2D(double x, double y)
{
X = x;
Y = y;
}
public override string ToString() => $"{X:N3}; {Y:N3}";
}
好的,我们还有一个概念 Segment 或分隔的 Line
:
public struct Segment2D
{
public Point2D Start { get; }
public Point2D End { get; }
public double Argument => Math.Atan2(End.Y - Start.Y , End.X - Start.X);
public Segment2D(Point2D start, Point2D end)
{
Start = start;
End = end;
}
}
最后但同样重要的是,我们有 圆 的概念:
public struct Circle2D
{
private const double FullCircleAngle = 2 * Math.PI;
public Point2D Center { get; }
public double Radius { get; }
public Circle2D(Point2D center, double radius)
{
if (radius <= 0)
throw new ArgumentOutOfRangeException(nameof(radius));
Center = center;
Radius = radius;
}
public IEnumerable<Point2D> GetPointsOfArch(int numberOfPoints, double startAngle, double endAngle)
{
double normalizedEndAngle;
if (startAngle < endAngle)
{
normalizedEndAngle = endAngle;
}
else
{
normalizedEndAngle = endAngle + FullCircleAngle;
}
var angleRange = normalizedEndAngle - startAngle;
angleRange = angleRange > FullCircleAngle ? FullCircleAngle : angleRange;
var step = angleRange / numberOfPoints;
var currentAngle = startAngle;
while (currentAngle <= normalizedEndAngle)
{
var x = Center.X + Radius * Math.Cos(currentAngle);
var y = Center.Y + Radius * Math.Sin(currentAngle);
yield return new Point2D(x, y);
currentAngle += step;
}
}
public IEnumerable<Point2D> GetPoints(int numberOfPoints)
=> GetPointsOfArch(numberOfPoints, 0, FullCircleAngle);
}
研究GetPointsOfArch
的实现,应该不会太难理解。
现在,要解决您的问题,您可以这样做:
var myCircle = new Circle2D(new Point2D(centerX, centerY), radius);
var line1 = ....
var line2 = ....
var archPoints = myCircle.GetPointsOfArch(number, line2.Argument, line1.Argument);
这不是更容易阅读、理解和理解吗?
我找不到在两条线之间绘制 ARC 的方法。我的约束是:我必须计算这个圆弧笔划点。因为我正在使用 InkCanvas 并且我必须逐点绘制此弧线,所以我无法将任何对象放到屏幕或 canvas 上。所以我知道我可以用 PATH 对象绘制任何弧线并使用 ArcSegment。使用此方法是的,我可以绘制圆弧,但它不是 Canvas 上的笔划点。因此我无法删除或保存它。 不管怎样,我需要逐点计算这个拱门。
我有像这样在 canvas 上画圆的代码:
Stroke GetCircleStroke(int centerX, int centerY, int radiusX, int radiusY,double angletoDraw=2.0)
{
StylusPointCollection strokePoints = new StylusPointCollection();
int numTotalSteps = 180;
for (int i = 0; i <= numTotalSteps; i++)
{
double angle = angletoDraw * Math.PI * (double)i / (double)numTotalSteps;
StylusPoint sp = new StylusPoint();
//compute x and y points
sp.X = centerX + Math.Cos(angle) * radiusX;
sp.Y = centerY - Math.Sin(angle) * radiusY;
//add to the collection
strokePoints.Add(sp);
}
Stroke newStroke = new Stroke(strokePoints);
return newStroke;
}
我可以很容易地画圆,但是我找不到画弧的方法:(
我们知道中心点 X,Y,我们知道 Line1 和 Line2 坐标。就是不知道那个弧线是什么..
你能帮我这样计算圆弧点吗?
你有一些概念飞来飞去,比如 Line
/Segment
、Point
、Circle
等。不要把代码弄得一团糟,让我们试着把问题分解成更容易理解的更小的部分。
你有一个点的概念,好的,让我们实现一个:
public struct Point2D //omitted equality logic
{
public double X { get; }
public double Y { get; }
public Point2D(double x, double y)
{
X = x;
Y = y;
}
public override string ToString() => $"{X:N3}; {Y:N3}";
}
好的,我们还有一个概念 Segment 或分隔的 Line
:
public struct Segment2D
{
public Point2D Start { get; }
public Point2D End { get; }
public double Argument => Math.Atan2(End.Y - Start.Y , End.X - Start.X);
public Segment2D(Point2D start, Point2D end)
{
Start = start;
End = end;
}
}
最后但同样重要的是,我们有 圆 的概念:
public struct Circle2D
{
private const double FullCircleAngle = 2 * Math.PI;
public Point2D Center { get; }
public double Radius { get; }
public Circle2D(Point2D center, double radius)
{
if (radius <= 0)
throw new ArgumentOutOfRangeException(nameof(radius));
Center = center;
Radius = radius;
}
public IEnumerable<Point2D> GetPointsOfArch(int numberOfPoints, double startAngle, double endAngle)
{
double normalizedEndAngle;
if (startAngle < endAngle)
{
normalizedEndAngle = endAngle;
}
else
{
normalizedEndAngle = endAngle + FullCircleAngle;
}
var angleRange = normalizedEndAngle - startAngle;
angleRange = angleRange > FullCircleAngle ? FullCircleAngle : angleRange;
var step = angleRange / numberOfPoints;
var currentAngle = startAngle;
while (currentAngle <= normalizedEndAngle)
{
var x = Center.X + Radius * Math.Cos(currentAngle);
var y = Center.Y + Radius * Math.Sin(currentAngle);
yield return new Point2D(x, y);
currentAngle += step;
}
}
public IEnumerable<Point2D> GetPoints(int numberOfPoints)
=> GetPointsOfArch(numberOfPoints, 0, FullCircleAngle);
}
研究GetPointsOfArch
的实现,应该不会太难理解。
现在,要解决您的问题,您可以这样做:
var myCircle = new Circle2D(new Point2D(centerX, centerY), radius);
var line1 = ....
var line2 = ....
var archPoints = myCircle.GetPointsOfArch(number, line2.Argument, line1.Argument);
这不是更容易阅读、理解和理解吗?