如何在SQL Server中从@s线段中点向@d线段绘制垂直线段
实现方案
你需要手动计算@s中点在@d所在直线上的垂直投影点,再把投影点限制在@d线段范围内,最后生成连线即可,完整代码如下:
-- 原始线段定义 declare @s geometry = geometry::STGeomFromText ( 'LINESTRING(' + convert(varchar(max),35.688889,128) +' '+ convert(varchar(max),51.314722,128) +', '+convert(varchar(max),32.750833,128) +' '+ convert(varchar(max),51.862778,128)+')',0 ); declare @d geometry = geometry::STGeomFromText ( 'LINESTRING(' + convert(varchar(max),34.761111,128) +' '+ convert(varchar(max),52.144444,128) +', '+convert(varchar(max),33.56,128) +' '+ convert(varchar(max),53.4475,128)+')',0 ); -- 1. 取@s线段的中点 DECLARE @P geometry = @s.STCentroid(); DECLARE @Px float = @P.STX, @Py float = @P.STY; -- 2. 提取@d线段的两个端点 DECLARE @A geometry = @d.STStartPoint(); DECLARE @B geometry = @d.STEndPoint(); DECLARE @Ax float = @A.STX, @Ay float = @A.STY; DECLARE @Bx float = @B.STX, @By float = @B.STY; -- 3. 计算投影参数t DECLARE @ABx float = @Bx - @Ax; DECLARE @ABy float = @By - @Ay; DECLARE @APx float = @Px - @Ax; DECLARE @APy float = @Py - @Ay; -- 加NULLIF避免@d退化为点时的除零错误 DECLARE @t float = (@APx * @ABx + @APy * @ABy) / NULLIF(@ABx * @ABx + @ABy * @ABy, 0); -- 4. 限制t范围,保证投影点落在@d线段上 SET @t = IIF(@t < 0, 0, IIF(@t > 1, 1, @t)); -- 5. 计算最终交点坐标 DECLARE @Qx float = @Ax + @t * @ABx; DECLARE @Qy float = @Ay + @t * @ABy; DECLARE @Q geometry = geometry::Point(@Qx, @Qy, 0); -- 6. 生成目标连线 DECLARE @result geometry = geometry::STLineFromText('LINESTRING(' + CONVERT(varchar(50), @Px, 128) + ' ' + CONVERT(varchar(50), @Py, 128) + ', ' + CONVERT(varchar(50), @Qx, 128) + ' ' + CONVERT(varchar(50), @Qy, 128) + ')', 0); -- 可选验证:计算向量点积,t在0~1区间时点积接近0,说明两条线垂直 DECLARE @QBx float = @Bx - @Qx, @QBy float = @By - @Qy; DECLARE @QPx float = @Px - @Qx, @QPy float = @Py - @Qy; DECLARE @dotProduct float = @QBx * @QPx + @QBy * @QPy;
说明
- 当计算出的
t值落在[0,1]区间内时,生成的@result连线与@d线段完全垂直 - 如果
t超出[0,1]区间,说明s中点在@d所在直线上的垂直投影落在@d线段外,此时会取@d上距离投影点最近的端点作为交点,该场景下无法实现90度夹角,属于几何客观限制
内容的提问来源于stack exchange,提问作者Iman Ghazanfarpour
相关产品推荐
相关产品推荐

