Trong khi tìm kiếm một giải pháp tính toán góc tương ứng với độ dài cung nhất định, tôi tình cờ thấy câu hỏi này và câu trả lời hiện tại. Thật không may, câu trả lời này cũng như bất kỳ tài nguyên nào khác mà tôi tìm thấy trên web có thể được sử dụng trực tiếp để thực hiện.
Rõ ràng, tính toán nghịch đảo của hàm độ dài cung (cũng được cung cấp trong câu hỏi) là rất khó. Nhưng một phép tính gần đúng của nghịch đảo này bằng Phương pháp lặp Newton là có thể. Sau đây là một lớp chủ yếu cung cấp hai phương thức:
computeArcLength(double alpha, double angleRad)
: Tính độ dài cung của một điểm trên Vòng xoắn ốc Archimedean trong đó alpha
khoảng cách giữa các lần quay liên tiếp và angleRad
là góc tính theo radian
computeAngle(double alpha, double arcLength, double epsilon)
: Tính góc mà điểm cho độ dài cung đã cho nằm trên Vòng xoắn ốc Archimedean, trong đó alpha
khoảng cách giữa các lần quay liên tiếp và epsilon
là ngưỡng xấp xỉ của Lặp lại Newton
Mã được triển khai ở đây trong Java, nhưng các phương thức cốt lõi này phải là ngôn ngữ không thể tin được:
import java.awt.geom.Point2D;
/**
* A class for computations related to an Archimedean Spiral
*/
class ArchimedeanSpiral
{
/**
* Computes an approximation of the angle at which an Archimedean Spiral
* with the given distance between successive turnings has the given
* arc length.<br>
* <br>
* Note that the result is computed using an approximation, and not
* analytically.
*
* @param alpha The distance between successive turnings
* @param arcLength The desired arc length
* @param epsilon A value greater than 0 indicating the precision
* of the approximation
* @return The angle at which the desired arc length is achieved
* @throws IllegalArgumentException If the given arc length is negative
* or the given epsilon is not positive
*/
static double computeAngle(
double alpha, double arcLength, double epsilon)
{
if (arcLength < 0)
{
throw new IllegalArgumentException(
"Arc length may not be negative, but is "+arcLength);
}
if (epsilon <= 0)
{
throw new IllegalArgumentException(
"Epsilon must be positive, but is "+epsilon);
}
double angleRad = Math.PI + Math.PI;
while (true)
{
double d = computeArcLength(alpha, angleRad) - arcLength;
if (Math.abs(d) <= epsilon)
{
return angleRad;
}
double da = alpha * Math.sqrt(angleRad * angleRad + 1);
angleRad -= d / da;
}
}
/**
* Computes the arc length of an Archimedean Spiral with the given
* parameters
*
* @param alpha The distance between successive turnings
* @param angleRad The angle, in radians
* @return The arc length
* @throws IllegalArgumentException If the given alpha is negative
*/
static double computeArcLength(
double alpha, double angleRad)
{
if (alpha < 0)
{
throw new IllegalArgumentException(
"Alpha may not be negative, but is "+alpha);
}
double u = Math.sqrt(1 + angleRad * angleRad);
double v = Math.log(angleRad + u);
return 0.5 * alpha * (angleRad * u + v);
}
/**
* Compute the point on the Archimedean Spiral for the given parameters.<br>
* <br>
* If the given result point is <code>null</code>, then a new point will
* be created and returned.
*
* @param alpha The distance between successive turnings
* @param angleRad The angle, in radians
* @param result The result point
* @return The result point
* @throws IllegalArgumentException If the given alpha is negative
*/
static Point2D computePoint(
double alpha, double angleRad, Point2D result)
{
if (alpha < 0)
{
throw new IllegalArgumentException(
"Alpha may not be negative, but is "+alpha);
}
double distance = angleRad * alpha;
double x = Math.sin(angleRad) * distance;
double y = Math.cos(angleRad) * distance;
if (result == null)
{
result = new Point2D.Double();
}
result.setLocation(x, y);
return result;
}
/**
* Private constructor to prevent instantiation
*/
private ArchimedeanSpiral()
{
// Private constructor to prevent instantiation
}
}
Một ví dụ về cách sử dụng mục tiêu này cho mục tiêu được mô tả trong câu hỏi được đưa ra trong đoạn trích này: Nó tạo ra một số điểm nhất định trên hình xoắn ốc, với khoảng cách (độ dài cung!) Mong muốn giữa các điểm:
import java.awt.geom.Point2D;
import java.util.Locale;
public class ArchimedeanSpiralExample
{
public static void main(String[] args)
{
final int numPoints = 50;
final double pointArcDistance = 0.1;
final double alpha = 0.5;
final double epsilon = 1e-5;
double totalArcLength = 0.0;
double previousAngleRad = 0.0;
for (int i=0; i<numPoints; i++)
{
double angleRad =
ArchimedeanSpiral.computeAngle(alpha, totalArcLength, epsilon);
Point2D point =
ArchimedeanSpiral.computePoint(alpha, angleRad, null);
totalArcLength += pointArcDistance;
// Compute and print the arc lengths, for validation:
double currentArcLength =
ArchimedeanSpiral.computeArcLength(alpha, angleRad);
double previousArcLength =
ArchimedeanSpiral.computeArcLength(alpha, previousAngleRad);
double arcDistance = (currentArcLength - previousArcLength);
System.out.printf(Locale.ENGLISH,
"Point (%6.2f, %6.2f distance in arc "
+ "length from previous is %6.2f\n",
point.getX(), point.getY(), arcDistance);
previousAngleRad = angleRad;
}
}
}
Các thực tế chiều dài hồ quang khoảng cách các điểm tính toán được in, và người ta có thể thấy rằng họ đang có trong thực tế cách đều, với mong muốn khoảng cách chiều dài hồ quang.