Sambil mencari solusi menghitung sudut yang sesuai dengan panjang busur tertentu, saya menemukan pertanyaan ini dan jawaban saat ini. Sayangnya, baik jawaban ini maupun sumber daya lain yang saya temukan di web tidak dapat langsung digunakan untuk implementasi.
Jelas, menghitung kebalikan dari fungsi panjang busur (yang juga disediakan dalam pertanyaan) sangat sulit. Tetapi perkiraan inversi ini menggunakan Metode Iteratif Newton dimungkinkan. Berikut ini adalah kelas yang terutama menawarkan dua metode:
computeArcLength(double alpha, double angleRad)
: Menghitung panjang busur titik pada Archimedean Spiral di mana alpha
jarak antara putaran yang berurutan, dan angleRad
merupakan sudut dalam radian
computeAngle(double alpha, double arcLength, double epsilon)
: Menghitung sudut di mana titik untuk panjang busur yang diberikan terletak pada Archimedean Spiral, di mana alpha
jarak antara putaran yang berurutan, dan epsilon
merupakan ambang perkiraan untuk Iterasi Newton
Kode ini diterapkan di sini di Jawa, tetapi metode inti ini harus cukup agnostik-bahasa:
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
}
}
Contoh cara menggunakan ini untuk tujuan yang dijelaskan dalam pertanyaan diberikan dalam cuplikan ini: Ini menghasilkan sejumlah titik pada spiral, dengan jarak yang diinginkan (panjang busur!) Antara titik-titik:
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;
}
}
}
The aktual panjang busur jarak poin dihitung dicetak, dan satu dapat melihat bahwa mereka sebenarnya berjarak sama, dengan yang diinginkan panjang busur kejauhan.