
SymPy 几何模块线型实体完全指南Line、Ray 与 Segment 的 API 与源码解析【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy本篇技术指南围绕 SymPy 几何模块中的线型linear实体展开系统讲解 doc/src/modules/geometry/lines.rst 所声明的全部 11 个类抽象基类LinearEntity、二维/三维的Line、Ray、Segment及其 2D/3D 具体子类。读完本文你将掌握如何用两点、点加斜率、方向向量或方程四种方式构造直线如何计算夹角、交点、距离、投影与垂线以及 SymPy 内部如何用仿射秩affine rank和线性代数方法统一处理平面内与空间中的相交判定——所有结论均有 line.py 源码与 test_line.py 测试用例可查证。文档定位从 autodoc 声明到真正的 API 来源lines.rst本身是一个 Sphinx autodoc 声明文件正文由.. autoclass::指令从源码 docstring 自动生成因此理解本主题必须回到实现文件全部线型实体的实现位于 sympy/geometry/line.py共 2878 行文档声明的 11 个类依次为LinearEntity、Line、Ray、Segment、LinearEntity2D、Line2D、Ray2D、Segment2D、LinearEntity3D、Line3D、Ray3D、Segment3D模块导出见 sympy/geometry/init.py其中Line, Ray, Segment, Line2D, Segment2D, Ray2D, Line3D, Segment3D, Ray3D均从sympy.geometry.line导入并进入__all__因此用户可直接from sympy import Line, Ray, Segment使用几何模块的整体定位可参见 doc/src/modules/geometry/index.rst支持创建二维几何实体并查询其性质以数值实体为主要场景同时支持符号表示。所有类共享同一继承骨架见 line.pyGeometryEntity → GeometrySet → LinearEntity → {Line, Ray, Segment} → LinearEntity2D → {Line2D, Ray2D, Segment2D} → LinearEntity3D → {Line3D, Ray3D, Segment3D}LinearEntity与LinearEntity2D/3D均为抽象基类docstring 明确 not meant to be instantiated实际使用的是六个具体类。Line、Ray、Segment的__new__会依据输入点的维度自动返回对应的 2D 或 3D 子类实例。LinearEntity所有线型实体的公共能力LinearEntity是 n 维欧氏空间中所有线型实体Line、Ray、Segment的基类定义了方向、长度、包含性、相交、夹角、投影等核心语义。公共属性属性含义实现位置p1/p2定义实体的两个点line.py直接返回self.args[0]与self.args[1]points两个定义点组成的元组(p1, p2)line.pydirection方向向量即p2 - p1line.py可用.unit归一化length实体长度Line/Ray为ooSegment为实际距离line.pyambient_dimension所在空间维度2 或 3line.py即len(self.p1)需要注意点的顺序决定direction的方向进而影响angle_between等角度计算的符号语义——文档示例中Line((0,0),(1,0))与Line((1,1),(0,0))对同一条线给出互为补角的答案。角度计算angle_between 与 smallest_angle_betweenangle_between(l1, l2)返回两条线方向向量夹角的非钝角补全取值范围[0, π]由点积公式实现line.pyacos(v1.dot(v2)/(abs(v1)*abs(v2)))smallest_angle_between(l1, l2)则返回两线在交点处形成的锐角取值范围[0, π/2]实现仅多了一层绝对值line.pyacos(abs(v1.dot(v2))/(abs(v1)*abs(v2)))两方法都要求参数为LinearEntity否则抛出TypeError(Must pass only LinearEntity objects)。源码 docstring 给出了直观示例 from sympy import Line e Line((0, 0), (1, 0)) ne Line((0, 0), (1, 1)) sw Line((1, 1), (0, 0)) ne.angle_between(e) pi/4 sw.angle_between(e) 3*pi/4 sw.smallest_angle_between(e) pi/43D 下同样适用 from sympy import Point3D, Line3D p1, p2, p3 Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(-1, 2, 0) l1, l2 Line3D(p1, p2), Line3D(p2, p3) l1.angle_between(l2) acos(-sqrt(2)/3)参数化点arbitrary_pointarbitrary_point(parametert)返回p1 (p2 - p1)*t即线上参数化点t0对应p1t1对应p2line.py。若参数名已出现在实体定义的自由符号中会抛出ValueError参数被强制为实数_symbol(parameter, realTrue) from sympy import Point, Line p1, p2 Point(1, 0), Point(5, 3) Line(p1, p2).arbitrary_point() Point2D(4*t 1, 3*t)该方法是内部许多算法的基础random_point通过替换参数生成随机点intersection在处理含浮点坐标的共面相交时通过求解两个arbitrary_point的相等方程并检查参数范围来判定归属。相交判定intersectionintersection(other)是线型实体最常用的方法接受Point或任意LinearEntity返回几何实体列表line.py。其算法在源码中以仿射秩Point.affine_rank为分水岭rank 1共线按双方类型组合调用三个内部辅助函数——intersect_parallel_rays、intersect_parallel_ray_and_segment、intersect_parallel_segments基于_span_test判断点相对p1是否在方向向量的正半张成空间内返回 -1/0/1确定平行射线/线段的重叠部分rank 2共面不共线先检查方向是否成标量倍数平行则返回[]否则构造矩阵方程t*d p1 s*d p1用增广矩阵rref(simplifyTrue)求解交点line.py。若实体含浮点坐标导致精确包含判定失败会退化到参数化求解并检查参数符号rank 为其他异面 skew直接返回[]。 from sympy import Point, Line, Segment p1, p2, p3 Point(0, 0), Point(1, 1), Point(7, 7) l1 Line(p1, p2) l1.intersection(p3) [Point2D(7, 7)] p4, p5 Point(5, 0), Point(0, 3) l1.intersection(Line(p4, p5)) [Point2D(15/8, 15/8)] l1.intersection(Segment(Point(0, 5), Point(2, 6))) []平行、垂直与相似is_parallel(l1, l2)判断l1.direction与l2.direction是否互为标量倍数line.pyis_perpendicular(l1, l2)判断方向向量点积是否等于 0line.py用S.Zero.equals处理符号表达式求值is_similar(other)返回 True 当且仅当二者共线line.py实现为Line(self.p1, self.p2).contains(other)。平行线、垂线与投影parallel_line(p)返回过点p且与自身平行的Line(p, p self.direction)line.pyperpendicular_line(p)返回过点p的垂线line.py。2D 实现直接取self.direction.orthogonal_direction任意两条平面直线必相交更快3D 实现则用self.projection(p)求投影点docstring 明确3D 中垂线的第一个点是通过点p第二个点任意地落在原直线上perpendicular_segment(p)返回从p到直线的垂线段Segment(p, p2)其中p2是垂线与直线的唯一交点line.py若p本身在线上则直接返回点pprojection(other)将点、线、射线或线段投影到自身line.py返回类型与输入类型匹配。对点实现为Point.project(p - self.p1, self.direction) self.p1对线型实体则投影两个端点后用Intersection收缩到自身范围内并保证投影方向与自身一致。 from sympy import Point, Line l1 Line(Point(0, 0), Point(1, 1)) l1.perpendicular_segment(Point(4, 0)) Segment2D(Point2D(4, 0), Point2D(2, 2)) l1.projection(Point(1, 0)) # 等价于 (1,0) 投影到 yx 上符号坐标示例见源码 Point2D(1/2, 1/2)共点性与角平分线are_concurrent(*lines)静态方法判断一组线型实体是否交于同一点line.py实现为Intersection(*lines)是含 1 个元素的有限集bisectors(other)返回过两线交点且共面的两条角平分线line.py以两条单位方向向量之和/差为方向构造Line from sympy import Point3D, Line3D r1 Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)) r2 Line3D(Point3D(0, 0, 0), Point3D(0, 1, 0)) r1.bisectors(r2) [Line3D(Point3D(0, 0, 0), Point3D(1, 1, 0)), Line3D(Point3D(0, 0, 0), Point3D(1, -1, 0))]Line无限直线与四种构造方式Line表示空间中的无限直线line.py根据p1的维度自动子类化为Line2D或Line3D。其__new__支持四种构造方式两个不同点Line(Point(2,3), Point(3,5))一个点 slope关键字仅 2DLine(Point(0,0), slope0)源码将斜率转为方向增量(1, slope)斜率为无穷时令dx0, dy1表示竖直直线line.py一个点 direction_ratio关键字仅 3DLine3D(Point3D(...), direction_ratio[2,8,8])方向比率长度必须为 3方程仅 2DLine(3*x y 18)或Line(Eq(3*a b, -18), xa, yb)内部用linear_coeffs提取系数a, b, c当b≠0时转为Line((0, -c/b), slope-a/b)当a≠0竖直时转为Line((-c/a, 0), slopeoo)line.py。此外还可传入另一个线型实体例如Line(s)其中s是Segment。Line 专有方法方法说明contains(other)判定点或线型实体是否在线上基于Point.is_collinearline.py注意l1 l2与l1 in l2语义不同反向定义的线不相等但互相包含distance(other)点到直线的最短距离line.py若点在线上返回 0否则返回perpendicular_segment(other).lengthequals(other)数学实体相等判定即四点共线检查line.pyplot_interval()绘图参数区间[t, -5, 5]line.pyLine2D额外提供slope斜率竖直直线返回ooline.pycoefficients(a, b, c)满足ax by c 0line.pyequation(xx, yy)返回形如-3*x 4*y 3的表达式line.py可自定义轴变量名。 from sympy import Line, Point L Line(Point(2, 3), Point(3, 5)) L.equation() -2*x y 1 L.coefficients (-2, 1, 1)Line3D的equation(x, y, z)返回定义空间直线的两个联立方程元组line.py内部通过引入参数k联立三个方向方程再消元得到。其distance(other)还支持Point3D、Line3D与Plane平行直线取点到线距离异面直线则用方向向量叉积构造法向量平面再求点到平面距离line.py from sympy.geometry import Line3D Line3D((0, 0, 0), (0, 0, 1)).distance(Line3D((0, 1, 0), (1, 1, 1))) 1Ray带源点的半直线Ray表示带源点与方向的半直线line.py按维度自动子类化为Ray2D/Ray3D。构造方式除两点外还支持角度Ray(Point(0, 0), anglepi/4)弧度逆时针为正。源码对角度做了象限分解_pi_coeff识别 π 的有理数倍对 0、π/2、π、3π/2 等特殊角直接给出单位向量其余情况用Piecewise与tan组合构造方向点line.py。关键属性与方法source源点即p1line.pyxdirection/ydirection射线在 x/y 方向上的符号oo、-oo或 0垂直/水平时对应方向为 0line.pyRay3D额外提供zdirectionline.pycontains(other)点在线方向上共线且方向点积非负才判定包含同时支持Segment/Ray子集判定line.pydistance(other)射线到点的距离先投影再判断投影点是否在射线上否则取到源点的距离line.pyplot_interval()返回[t, 0, 10]Ray2D.closing_angle(r1, r2)返回 r2 需旋转多少弧度才能与 r1 同向逆时针为正基于atan2计算两方向角之差并做符号归一line.py仅接受Ray2D参数 from sympy import Ray, pi r1 Ray((0, 0), (1, 0)) r2 r1.rotate(-pi/2) r1.closing_angle(r2) pi/2Segment有限线段Segment表示空间中的有限线段line.py自动子类化为Segment2D/Segment3D。构造要求两个点当两点重合时Segment2D.__new__/Segment3D.__new__直接返回该点退化情形。关键属性与方法length线段长度即Point.distance(self.p1, self.p2)midpoint中点slope2D斜率contains(other)点判定使用共线 三角不等式技巧——判断|d1| |d2| |d|是否恒成立line.py并兼容Segment2D的包围盒快速路径若无法判定则抛出Undecidabledistance(other)到点的最短距离通过方向向量与两端点向量的点积符号分成三种情形垂足落在段内则取点到直线距离否则取到较近端点的距离line.pyperpendicular_bisector(pNone)返回线段的垂直平分线若提供点p且p在平分线上则返回连接p与中点的Segment否则返回Lineline.pyplot_interval()返回[t, 0, 1]。 from sympy import Point, Segment s Segment(Point(4, 3), Point(1, 1)) s.slope, s.length, s.midpoint (2/3, sqrt(13), Point2D(5/2, 2)) s.perpendicular_bisector() Line2D(Point2D(5/2, 2), Point2D(5/2, -1)) # 输出细节以实际运行结果为准LinearEntity2D / LinearEntity3D维度专属能力两个维度基类补充了各自的专属属性均不直接实例化LinearEntity2Dline.pybounds包围矩形(xmin, ymin, xmax, ymax)slope斜率竖直为ooperpendicular_line(p)2D 快速实现直接取正交方向。LinearEntity3Dline.pydirection_ratio方向比率[dx, dy, dz]未归一化由p1.direction_ratio(p2)计算direction_cosine归一化方向余弦平方和为 1可用于验证。 from sympy import Point3D, Line3D l Line3D(Point3D(0, 0, 0), Point3D(5, 3, 1)) l.direction_ratio [5, 3, 1] l.direction_cosine [sqrt(35)/7, 3*sqrt(35)/35, sqrt(35)/35]边界行为与错误约定源码中的参数校验与异常约定值得注意LinearEntity.__new__要求两个不同的点ValueError且两点维度必须一致Segment2D/3D对退化两点相同则返回单个PointLine方程构造中若给x/y之外的关键字会抛ValueError第二个参数既非有效Point又未用slope关键字时Line2D会提示如果它是斜率请用关键字 slope 传入line.pyangle_between、smallest_angle_between、is_parallel、is_perpendicular对非LinearEntity参数统一抛TypeError当包含关系无法确定时__contains__会抛出sympy.utilities.misc.Undecidable测试 test_line.py 中的test_contains与test_contains_nonreal_symbols专门覆盖了符号坐标下的不可判定场景这些行为均有对应测试验证例如test_validation_for_linear_entity_methods参数类型校验、test_intersection_2d/test_intersection_3d相交算法、test_distance_2d/test_distance_3d距离、test_ray_generation角度构造射线、test_bisectors角平分线等共 40 余个测试函数是深入理解各方法语义的最佳参考。实战小结把四类构造、两类角度 API 与一整套几何查询方法组合起来可以完成常见计算任务from sympy import Line, Ray, Segment, Point, pi # 构造两点 / 点斜率 / 点方向比率 / 方程 l Line(Point(0, 0), Point(1, 1)) l2 Line(Point(1, 0), slope1) # 平行于 l r Ray(Point(0, 0), anglepi/4) # 与 l 同方向的射线 s Segment(Point(0, 2), Point(2, 0)) # 查询 l.angle_between(l2) # 0 l.is_parallel(l2) # True l.intersection(s) # 与线段求交 l.perpendicular_segment(Point(2, 2)) # 垂线段所有类与方法的权威说明参数、返回值、示例均随源码 docstring 自动汇入 lines.rst 对应的 API 章节若要进一步深挖实现直接阅读 sympy/geometry/line.py 及其测试 test_line.py 即可获得与文档一致的完整契约。【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考