From fbbc7240c86dfa387d0c367ed89a4de568546707 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Wed, 6 Jun 2012 12:42:02 +0545 Subject: [PATCH] geometry: perpendicular segment and orthocenter corrections The perpendicular segment may not terminate on the LinearEntity so the intersection must be done with the line containing the linear entity. The same sort of reasoning applies to the orthocenter calculation: since the altitudes are segments, they may not intersect within the triangle so lines containing the altitudes should be used to find the intersection. --- sympy/geometry/line.py | 10 ++++++++-- sympy/geometry/polygon.py | 7 ++++--- sympy/geometry/tests/test_geometry.py | 8 ++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/sympy/geometry/line.py b/sympy/geometry/line.py index 3f63e7637b9a..2ab73ecc21b1 100644 --- a/sympy/geometry/line.py +++ b/sympy/geometry/line.py @@ -399,7 +399,7 @@ def perpendicular_line(self, p): """ d1, d2 = (self.p1 - self.p2).args - if d2 == 0: # If an horizontal line + if d2 == 0: # If a horizontal line if p.y == self.p1.y: # if p is on this linear entity return Line(p, p + Point(0, 1)) else: @@ -412,6 +412,10 @@ def perpendicular_line(self, p): def perpendicular_segment(self, p): """Create a perpendicular line segment from `p` to this line. + The enpoints of the segment are ``p`` and the closest point in + the line containing self. (If self is not a line, the point might + not be in self.) + Parameters ========== @@ -443,12 +447,14 @@ def perpendicular_segment(self, p): True >>> p3 in s1 True + >>> l1.perpendicular_segment(Point(4, 0)) + Segment(Point(2, 2), Point(4, 0)) """ if p in self: return p pl = self.perpendicular_line(p) - p2 = self.intersection(pl)[0] + p2 = Line(self).intersection(pl)[0] return Segment(p, p2) @property diff --git a/sympy/geometry/polygon.py b/sympy/geometry/polygon.py index 1d096f141404..af382f0da636 100644 --- a/sympy/geometry/polygon.py +++ b/sympy/geometry/polygon.py @@ -1824,8 +1824,9 @@ def is_right(self): def altitudes(self): """The altitudes of the triangle. - An altitude of a triangle is a straight line through a vertex and - perpendicular to the opposite side. + An altitude of a triangle is a segment through a vertex, + perpendicular to the opposite side, with length being the + height of the vertex measured from the line containing the side. Returns ======= @@ -1884,7 +1885,7 @@ def orthocenter(self): """ a = self.altitudes v = self.vertices - return a[v[0]].intersection(a[v[1]])[0] + return Line(a[v[0]]).intersection(Line(a[v[1]]))[0] @property def circumcenter(self): diff --git a/sympy/geometry/tests/test_geometry.py b/sympy/geometry/tests/test_geometry.py index 0f4fa5859647..b9cef24a08ae 100644 --- a/sympy/geometry/tests/test_geometry.py +++ b/sympy/geometry/tests/test_geometry.py @@ -776,6 +776,14 @@ def test_polygon(): assert altitudes[p2] == s1[0] assert altitudes[p3] == s1[2] assert t1.orthocenter == p1 + t = S('''Triangle( + Point(100080156402737/5000000000000, 79782624633431/500000000000), + Point(39223884078253/2000000000000, 156345163124289/1000000000000), + Point(31241359188437/1250000000000, 338338270939941/1000000000000000))''') + assert t.orthocenter == S('''Point(-780660869050599840216997''' + '''79471538701955848721853/80368430960602242240789074233100000000000000,''' + '''20151573611150265741278060334545897615974257/16073686192120448448157''' + '''8148466200000000000)''') # Ensure assert len(intersection(*bisectors.values())) == 1