计算机图形学:线段的交点计算及代码实现

2025-12-04 18:12:08

文章目录

原理推导过程

代码实现Python代码C++代码应用示例

在计算机图形学、几何计算和工程领域中,经常需要计算两条线段的交点。本文将详细介绍线段交点计算的原理、公式推导过程以及代码实现。

原理

要计算两条线段的交点,我们首先需要确定这两条线段是否相交。线段可以由两个端点定义,设线段

A

B

AB

AB的端点为

A

(

x

1

,

y

1

)

A(x_1, y_1)

A(x1​,y1​)和

B

(

x

2

,

y

2

)

B(x_2, y_2)

B(x2​,y2​),线段

C

D

CD

CD的端点为

C

(

x

3

,

y

3

)

C(x_3, y_3)

C(x3​,y3​)和

D

(

x

4

,

y

4

)

D(x_4, y_4)

D(x4​,y4​)。

推导过程

确定线段的方程:线段(AB)和(CD)可以表示为参数方程:

A

B

:

{

x

=

x

1

+

t

(

x

2

x

1

)

y

=

y

1

+

t

(

y

2

y

1

)

(

0

t

1

)

AB: \begin{cases} x = x_1 + t(x_2 - x_1) \\ y = y_1 + t(y_2 - y_1) \end{cases} \quad (0 \leq t \leq 1)

AB:{x=x1​+t(x2​−x1​)y=y1​+t(y2​−y1​)​(0≤t≤1)

C

D

:

{

x

=

x

3

+

s

(

x

4

x

3

)

y

=

y

3

+

s

(

y

4

y

3

)

(

0

s

1

)

CD: \begin{cases} x = x_3 + s(x_4 - x_3) \\ y = y_3 + s(y_4 - y_3) \end{cases} \quad (0 \leq s \leq 1)

CD:{x=x3​+s(x4​−x3​)y=y3​+s(y4​−y3​)​(0≤s≤1)

设置交点条件:如果线段相交,那么存在

t

t

t和

s

s

s使得:

x

1

+

t

(

x

2

x

1

)

=

x

3

+

s

(

x

4

x

3

)

x_1 + t(x_2 - x_1) = x_3 + s(x_4 - x_3)

x1​+t(x2​−x1​)=x3​+s(x4​−x3​)

y

1

+

t

(

y

2

y

1

)

=

y

3

+

s

(

y

4

y

3

)

y_1 + t(y_2 - y_1) = y_3 + s(y_4 - y_3)

y1​+t(y2​−y1​)=y3​+s(y4​−y3​)

解方程组:解这个方程组得到

t

t

t和

s

s

s。

t

=

(

x

3

x

1

)

(

y

4

y

3

)

(

y

3

y

1

)

(

x

4

x

3

)

(

x

2

x

1

)

(

y

4

y

3

)

(

y

2

y

1

)

(

x

4

x

3

)

t = \frac{(x3 - x1)(y4 - y3) - (y3 - y1)(x4 - x3)}{(x2 - x1)(y4 - y3) - (y2 - y1)(x4 - x3)}

t=(x2−x1)(y4−y3)−(y2−y1)(x4−x3)(x3−x1)(y4−y3)−(y3−y1)(x4−x3)​

s

=

(

x

3

x

1

)

(

y

2

y

1

)

(

y

3

y

1

)

(

x

2

x

1

)

(

x

2

x

1

)

(

y

4

y

3

)

(

y

2

y

1

)

(

x

4

x

3

)

s = \frac{(x3 - x1)(y2 - y1) - (y3 - y1)(x2 - x1)}{(x2 - x1)(y4 - y3) - (y2 - y1)(x4 - x3)}

s=(x2−x1)(y4−y3)−(y2−y1)(x4−x3)(x3−x1)(y2−y1)−(y3−y1)(x2−x1)​ 如果

t

t

t和

s

s

s都在

[

0

,

1

]

[0, 1]

[0,1]区间内,那么线段相交。

计算交点:交点的坐标为:

P

(

x

1

+

t

(

x

2

x

1

)

,

y

1

+

t

(

y

2

y

1

)

)

P\left(x_1 + t(x_2 - x_1), y_1 + t(y_2 - y_1)\right)

P(x1​+t(x2​−x1​),y1​+t(y2​−y1​))

代码实现

Python代码

def line_intersection(A, B, C, D):

x1, y1 = A

x2, y2 = B

x3, y3 = C

x4, y4 = D

# 计算分母

denominator = (x2 - x1) * (y4 - y3) - (y2 - y1) * (x4 - x3)

if denominator == 0:

return None # 线段平行或重合

# 计算t和s

t = ((x3 - x1) * (y4 - y3) - (y3 - y1) * (x4 - x3)) / denominator

s = ((x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1)) / denominator

# 检查t和s是否在[0, 1]区间内

if 0 <= t <= 1 and 0 <= s <= 1:

return (x1 + t * (x2 - x1), y1 + t * (y2 - y1))

else:

return None # 线段不相交

C++代码

#include

struct Point {

double x, y;

};

Point line_intersection(Point A, Point B, Point C, Point D) {

double x1 = A.x, y1 = A.y;

double x2 = B.x, y2 = B.y;

double x3 = C.x, y3 = C.y;

double x4 = D.x, y4 = D.y;

// 计算分母

double denominator = (x2 - x1) * (y4 - y3) - (y2 - y1) * (x4 - x3);

if (denominator == 0) {

return {0, 0}; // 线段平行或重合

}

// 计算t和s

double t = ((x3 - x1) * (y4 - y3) - (y3 - y1) * (x4 - x3)) / denominator;

double s = ((x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1)) / denominator;

// 检查t和s是否在[0, 1]区间内

if (0 <= t && t <= 1 && 0 <= s && s <= 1) {

return {x1 + t * (x2 - x1), y1 + t * (y2 - y1)};

} else {

return {0, 0}; // 线段不相交

}

}

应用示例

import matplotlib.pyplot as plt

import numpy as np

from matplotlib.animation import FuncAnimation

def line_intersection(A, B, C, D):

x1, y1 = A

x2, y2 = B

x3, y3 = C

x4, y4 = D

# 计算分母

denominator = (x2 - x1) * (y4 - y3) - (y2 - y1) * (x4 - x3)

if denominator == 0:

return None # 线段平行或重合

# 计算t和s

t = ((x3 - x1) * (y4 - y3) - (y3 - y1) * (x4 - x3)) / denominator

s = ((x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1)) / denominator

# 检查t和s是否在[0, 1]区间内

if 0 <= t <= 1 and 0 <= s <= 1:

return (x1 + t * (x2 - x1), y1 + t * (y2 - y1))

else:

return None # 线段不相交

# 手动定义线段

segments = [

((0.3, 0.3), (0.8, 0.8), (0.2, 0.8), (0.8, 0.2)),

((0.2, 0.2), (0.8, 0.2), (0.5, 0.5), (0.8, 0.5)),

((0.1, 0.1), (0.7, 0.7), (0.6, 0.22), (0.8, 0.2)),

((0.3, 0.3), (0.7, 0.7), (0.4, 0.84), (0.8, 0.2)),

((0.2, 0.5), (0.8, 0.4), (0.6, 0.8), (0.7, 0.2)),

((0.2, 0.3), (0.8, 0.8), (0.5, 0.2), (0.8, 0.2))

]

fig, ax = plt.subplots()

ax.set_xlim(0, 1)

ax.set_ylim(0, 1)

ax.set_aspect('equal')

# 初始化绘图

line1, = ax.plot([], [], 'b-', animated=True)

line2, = ax.plot([], [], 'b-', animated=True)

point, = ax.plot([], [], 'ro', animated=True)

text = ax.text(0.5, 0.9, '', transform=ax.transAxes, ha='center')

def init():

line1.set_data([], [])

line2.set_data([], [])

point.set_data([], [])

text.set_text('')

return line1, line2, point, text

def animate(i):

A, B, C, D = segments[i]

intersection = line_intersection(A, B, C, D)

line1.set_data([A[0], B[0]], [A[1], B[1]])

line2.set_data([C[0], D[0]], [C[1], D[1]])

if intersection:

line1.set_color('r')

line2.set_color('r')

point.set_data([intersection[0]], [intersection[1]])

text.set_text(f'Intersection: ({intersection[0]:.2f}, {intersection[1]:.2f})')

else:

line1.set_color('b')

line2.set_color('b')

point.set_data([], []) # 修改这里

text.set_text('No Intersection')

return line1, line2, point, text

ani = FuncAnimation(fig, animate, init_func=init, frames=len(segments), interval=500, blit=True)

# 保存动图

ani.save('line_segments.gif', writer='pillow', fps=1)

plt.show()

运行效果如下