mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-12-19 07:00:35 +08:00
94 lines
3.0 KiB
Java
94 lines
3.0 KiB
Java
package com.thealgorithms.lineclipping;
|
|
|
|
import com.thealgorithms.lineclipping.utils.Line;
|
|
import com.thealgorithms.lineclipping.utils.Point;
|
|
|
|
/**
|
|
* @author shikarisohan
|
|
* @since 10/5/24
|
|
*
|
|
* * The Liang-Barsky line clipping algorithm is an efficient algorithm for
|
|
* * line clipping against a rectangular window. It is based on the parametric
|
|
* * equation of a line and checks the intersections of the line with the
|
|
* * window boundaries. This algorithm calculates the intersection points,
|
|
* * if any, and returns the clipped line that lies inside the window.
|
|
* *
|
|
* * Reference:
|
|
* * https://en.wikipedia.org/wiki/Liang%E2%80%93Barsky_algorithm
|
|
*
|
|
* Clipping window boundaries are defined as (xMin, yMin) and (xMax, yMax).
|
|
* The algorithm computes the clipped line segment if it's partially or
|
|
* fully inside the clipping window.
|
|
*/
|
|
public class LiangBarsky {
|
|
|
|
// Define the clipping window
|
|
double xMin;
|
|
double xMax;
|
|
double yMin;
|
|
double yMax;
|
|
|
|
public LiangBarsky(double xMin, double yMin, double xMax, double yMax) {
|
|
this.xMin = xMin;
|
|
this.yMin = yMin;
|
|
this.xMax = xMax;
|
|
this.yMax = yMax;
|
|
}
|
|
|
|
// Liang-Barsky algorithm to return the clipped line
|
|
public Line liangBarskyClip(Line line) {
|
|
double dx = line.end.x - line.start.x;
|
|
double dy = line.end.y - line.start.y;
|
|
|
|
double[] p = {-dx, dx, -dy, dy};
|
|
double[] q = {line.start.x - xMin, xMax - line.start.x, line.start.y - yMin, yMax - line.start.y};
|
|
|
|
double[] resultT = clipLine(p, q);
|
|
|
|
if (resultT == null) {
|
|
return null; // Line is outside the clipping window
|
|
}
|
|
|
|
return calculateClippedLine(line, resultT[0], resultT[1], dx, dy);
|
|
}
|
|
|
|
// clip the line by adjusting t0 and t1 for each edge
|
|
private double[] clipLine(double[] p, double[] q) {
|
|
double t0 = 0.0;
|
|
double t1 = 1.0;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
double t = q[i] / p[i];
|
|
if (p[i] == 0 && q[i] < 0) {
|
|
return null; // Line is outside the boundary
|
|
} else if (p[i] < 0) {
|
|
if (t > t1) {
|
|
return null;
|
|
} // Line is outside
|
|
if (t > t0) {
|
|
t0 = t;
|
|
} // Update t0
|
|
} else if (p[i] > 0) {
|
|
if (t < t0) {
|
|
return null;
|
|
} // Line is outside
|
|
if (t < t1) {
|
|
t1 = t;
|
|
} // Update t1
|
|
}
|
|
}
|
|
|
|
return new double[] {t0, t1}; // Return valid t0 and t1
|
|
}
|
|
|
|
// calculate the clipped line based on t0 and t1
|
|
private Line calculateClippedLine(Line line, double t0, double t1, double dx, double dy) {
|
|
double clippedX1 = line.start.x + t0 * dx;
|
|
double clippedY1 = line.start.y + t0 * dy;
|
|
double clippedX2 = line.start.x + t1 * dx;
|
|
double clippedY2 = line.start.y + t1 * dy;
|
|
|
|
return new Line(new Point(clippedX1, clippedY1), new Point(clippedX2, clippedY2));
|
|
}
|
|
}
|