Если у вас есть бесконечная линия, которая определяется точкой P
и нормализованным направлением R
, и вторая бесконечная линия, которая определяется точкой Q
и направлением S
, то точка пересечения бесконечных линий X
составляет:
alpha ... angle between Q-P and R
beta ... angle between R and S
gamma = 180° - alpha - beta
h = | Q - P | * sin(alpha)
u = h / sin(beta)
t = | Q - P | * sin(gamma) / sin(beta)
t = dot(Q-P, (S.y, -S.x)) / dot(R, (S.y, -S.x)) = determinant(mat2(Q-P, S)) / determinant(mat2(R, S))
u = dot(Q-P, (R.y, -R.x)) / dot(R, (S.y, -S.x)) = determinant(mat2(Q-P, R)) / determinant(mat2(R, S))
X = P + R * t = Q + S * u
См. также найти точку пересечения двух векторов независимо из направления
Если у вас есть инин от l1p1
до l1p2
и вторая строка от l2p1
до l2p2
, тогда:
P = l1p1
Q = l2p1;
R = normalize(l1p2 - l1p1)
S = normalize(l2p2 - l2p1)
normalize
вычисляет Единичный вектор вектора. Длина единичного вектора равна 1.
Поскольку линии не являются бесконечными, необходимо оценить, находится ли точка пересечения на отрезке. Вычислите длину линий и расстояния от начала залога до точки пересечения. Убедитесь, что расстояния (вычисленные с помощью Dot product ) больше> = 0 и <= длина линии. <br>В следующем
len1 = | l1p2 - l1p1 |
len2 = | l2p2 - l2p1 |
distOnL1 = dot(X - P, R);
distOnL2 = dot(X - Q, S);
intersecting = distOnL1 >= 0 AND distOnL1 <= len1 AND distOnL2 >= 0 AND distOnL2 <= len2
Это можно рассчитать с помощью PVector
следующим образом:
class TIntersection {
boolean valid = false;
PVector point = new PVector(0.0, 0.0);
}
// Intersect 2 endless lines
// line 1: line segment from `l1p1` to `l1p2`
// line 2: line segment from `l2p1` to `l2p2`
TIntersection Intersect(PVector l1p1, PVector l1p2, PVector l2p1, PVector l2p2) {
PVector P = l1p1;
PVector Q = l2p1;
PVector R = PVector.sub(l1p2, l1p1);
PVector S = PVector.sub(l2p2, l2p1);
float len1 = R.mag();
float len2 = S.mag();
R.normalize();
S.normalize();
PVector QP = PVector.sub(Q, P);
PVector SNV = new PVector(S.y, -S.x);
TIntersection isect = new TIntersection();
float t = QP.dot(SNV) / R.dot(SNV);
isect.point = PVector.add(P, PVector.mult(R, t));
if (!Float.isInfinite(isect.point.x) || !Float.isInfinite(isect.point.y)) {
float distOnL1 = PVector.sub(isect.point, P).dot(R);
float distOnL2 = PVector.sub(isect.point, Q).dot(S);
isect.valid = distOnL1 >= 0.0 && distOnL1 <= len1 && distOnL2 >= 0.0 && distOnL2 <= len2;
} else {
isect.valid = false;
}
return isect;
}
Возвращаемое значение функции имеет тип TIntersection
. Атрибут valid
равен true
, если есть пересечение и линии не параллельны. Атрибут point
типа PVector
является точкой пересечения, если она есть.
См. Пример:
<script src="https://cdnjs.cloudflare.com/ajax/libs/processing.js/1.6.6/processing.min.js"></script>
<canvas id="pjs"></canvas>
<script type="application/processing" data-processing-target="pjs">
class TIntersection {
boolean valid = false;
PVector point = new PVector(0.0, 0.0);
}
// Intersect 2 endless lines
// line 1: line segment from `l1p1` to `l1p2`
// line 2: line segment from `l2p1` to `l2p2`
TIntersection Intersect(PVector l1p1, PVector l1p2, PVector l2p1, PVector l2p2) {
PVector P = l1p1;
PVector Q = l2p1;
PVector R = PVector.sub(l1p2, l1p1);
PVector S = PVector.sub(l2p2, l2p1);
float len1 = R.mag();
float len2 = S.mag();
R.normalize();
S.normalize();
PVector QP = PVector.sub(Q, P);
PVector SNV = new PVector(S.y, -S.x);
TIntersection isect = new TIntersection();
float t = QP.dot(SNV) / R.dot(SNV);
isect.point = PVector.add(P, PVector.mult(R, t));
//if (!Float.isInfinite(isect.point.x) || !Float.isInfinite(isect.point.y)) {
float distOnL1 = PVector.sub(isect.point, P).dot(R);
float distOnL2 = PVector.sub(isect.point, Q).dot(S);
isect.valid = distOnL1 >= 0.0 && distOnL1 <= len1 && distOnL2 >= 0.0 && distOnL2 <= len2;
//} else {
// isect.valid = false;
//}
return isect;
}
ArrayList<PVector> poly;
PVector[] line_p, move;
void setup() {
size(500,500);
poly = new ArrayList();
poly.add(new PVector(175, 100));
poly.add(new PVector(175, 300));
poly.add(new PVector(200, 300));
poly.add(new PVector(225, 400));
poly.add(new PVector(275, 350));
poly.add(new PVector(275, 200));
poly.add(new PVector(325, 200));
poly.add(new PVector(325, 100));
line_p = new PVector[2];
line_p[0] = new PVector(150, 400);
line_p[1] = new PVector(380, 100);
move = new PVector[2];
move[0] = new PVector(random(2)-1, random(2)-1);
move[1] = new PVector(random(2)-1, random(2)-1);
}
void draw() {
// randomize points
for (int i=0; i < line_p.length; ++i ) {
line_p[i] = PVector.add(line_p[i], move[i]);
if (line_p[i].x < 50 || line_p[i].x > width-50)
move[i].x *= -1;
if (line_p[i].y < 50 || line_p[i].y > height-50)
move[i].y *= -1;
move[i].x = max(-1, min(1, move[i].x+random(0.2)-0.1));
move[i].y = max(-1, min(1, move[i].y+random(0.2)-0.1));
}
// clear background
background(0, 0, 0);
stroke(255);
fill(255, 0, 0);
// draw line
line(line_p[0].x, line_p[0].y, line_p[1].x, line_p[1].y);
// draw polygon and intersections
int intersections = 0;
for (int i = 0; i < poly.size(); i++) {
PVector poly_p1 = poly.get(i);
PVector poly_p2 = poly.get((i+1) % poly.size());
line(poly_p1.x, poly_p1.y, poly_p2.x, poly_p2.y);
TIntersection x = Intersect(line_p[0], line_p[1], poly_p1, poly_p2);
if (x.valid) {
ellipse(x.point.x, x.point.y, 10, 10);
intersections ++;
}
}
// draw intersection count
fill(255);
textSize(24);
text("intersections: " + str(intersections), 20, 40);
}
</script>