From 657cb6c7275a9c9273d63891fdfc01eebeb3eecb Mon Sep 17 00:00:00 2001 From: volkoshkursk Date: Thu, 10 Nov 2022 15:25:59 +0300 Subject: [PATCH 1/9] Feat: Add parameter tol to intersect_line --- src/skspatial/objects/line.py | 6 ++++-- src/skspatial/objects/line_segment.py | 7 +++++-- src/skspatial/objects/triangle.py | 10 ++++++++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/skspatial/objects/line.py b/src/skspatial/objects/line.py index b7ac370c..d172a414 100644 --- a/src/skspatial/objects/line.py +++ b/src/skspatial/objects/line.py @@ -475,7 +475,7 @@ def distance_line(self, other: Line) -> np.float64: return distance - def intersect_line(self, other: Line, **kwargs) -> Point: + def intersect_line(self, other: Line, tol: np.float64 = None, **kwargs) -> Point: """ Intersect the line with another. @@ -485,6 +485,8 @@ def intersect_line(self, other: Line, **kwargs) -> Point: ---------- other : Line Other line. + tol : np.float64, optional + Threshold below which values are considered zero. This value is passed to is_coplanar kwargs : dict, optional Additional keywords passed to :meth:`Vector.is_parallel`. @@ -560,7 +562,7 @@ def intersect_line(self, other: Line, **kwargs) -> Point: if self.direction.is_parallel(other.direction, **kwargs): raise ValueError("The lines must not be parallel.") - if not self.is_coplanar(other): + if not self.is_coplanar(other, tol=tol): raise ValueError("The lines must be coplanar.") # Vector from line A to line B. diff --git a/src/skspatial/objects/line_segment.py b/src/skspatial/objects/line_segment.py index 2ae3900d..27110a83 100644 --- a/src/skspatial/objects/line_segment.py +++ b/src/skspatial/objects/line_segment.py @@ -106,7 +106,7 @@ def contains_point(self, point: array_like, **kwargs) -> bool: return math.isclose(similarity, -1, **kwargs) - def intersect_line_segment(self, other: LineSegment) -> Point: + def intersect_line_segment(self, other: LineSegment, tol: np.float64 = None) -> Point: """ Intersect the line segment with another. @@ -114,6 +114,9 @@ def intersect_line_segment(self, other: LineSegment) -> Point: ---------- other : LineSegment + tol : np.float64, optional + Threshold below which values are considered zero. This value is passed to is_coplanar as tol and to is_collinear as abs_tol. + Returns ------- Point @@ -145,7 +148,7 @@ def intersect_line_segment(self, other: LineSegment) -> Point: line_a = Line.from_points(self.point_a, self.point_b) line_b = Line.from_points(other.point_a, other.point_b) - point_intersection = line_a.intersect_line(line_b) + point_intersection = line_a.intersect_line(line_b, tol=tol, abs_tol=tol) if tol is not None else line_a.intersect_line(line_b) point_on_segment_a = self.contains_point(point_intersection) point_on_segment_b = other.contains_point(point_intersection) diff --git a/src/skspatial/objects/triangle.py b/src/skspatial/objects/triangle.py index 6debe773..e405071d 100644 --- a/src/skspatial/objects/triangle.py +++ b/src/skspatial/objects/triangle.py @@ -498,12 +498,18 @@ def altitude(self, vertex: str) -> Line: raise ValueError("The vertex must be 'A', 'B', or 'C'.") - def orthocenter(self) -> Point: + def orthocenter(self, tol: np.float64 = None) -> Point: """ Return the orthocenter of the triangle. The orthocenter is the intersection point of the three altitudes. + Parameters + ---------- + tol : np.float64, optional + Threshold below which values are considered zero. This value is passed to is_coplanar as tol and to is_collinear as abs_tol. + + Returns ------- Point @@ -523,7 +529,7 @@ def orthocenter(self) -> Point: line_alt_a = self.altitude('A') line_alt_b = self.altitude('B') - return line_alt_a.intersect_line(line_alt_b) + return line_alt_a.intersect_line(line_alt_b, tol=tol, abs_tol=tol) if tol is not None else line_alt_a.intersect_line(line_alt_b) def classify(self, **kwargs: float) -> str: """ From c376ac0886521744a54c594a5a208f10d3e64313 Mon Sep 17 00:00:00 2001 From: volkoshkursk <30547621+volkoshkursk@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:01:22 +0300 Subject: [PATCH 2/9] Update src/skspatial/objects/line.py Co-authored-by: Andrew Hynes --- src/skspatial/objects/line.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skspatial/objects/line.py b/src/skspatial/objects/line.py index d172a414..aab43847 100644 --- a/src/skspatial/objects/line.py +++ b/src/skspatial/objects/line.py @@ -475,7 +475,7 @@ def distance_line(self, other: Line) -> np.float64: return distance - def intersect_line(self, other: Line, tol: np.float64 = None, **kwargs) -> Point: + def intersect_line(self, other: Line, check_coplanar: bool = True, **kwargs) -> Point: """ Intersect the line with another. From 67007d81d410765f4668439befdc62aec775cb9d Mon Sep 17 00:00:00 2001 From: volkoshkursk <30547621+volkoshkursk@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:01:29 +0300 Subject: [PATCH 3/9] Update src/skspatial/objects/line_segment.py Co-authored-by: Andrew Hynes --- src/skspatial/objects/line_segment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skspatial/objects/line_segment.py b/src/skspatial/objects/line_segment.py index 27110a83..3506a867 100644 --- a/src/skspatial/objects/line_segment.py +++ b/src/skspatial/objects/line_segment.py @@ -148,7 +148,7 @@ def intersect_line_segment(self, other: LineSegment, tol: np.float64 = None) -> line_a = Line.from_points(self.point_a, self.point_b) line_b = Line.from_points(other.point_a, other.point_b) - point_intersection = line_a.intersect_line(line_b, tol=tol, abs_tol=tol) if tol is not None else line_a.intersect_line(line_b) + point_intersection = line_a.intersect_line(line_b, **kwargs) point_on_segment_a = self.contains_point(point_intersection) point_on_segment_b = other.contains_point(point_intersection) From 1b2789ce561ce7a34321d37c6a3aad8eed036c80 Mon Sep 17 00:00:00 2001 From: volkoshkursk <30547621+volkoshkursk@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:01:45 +0300 Subject: [PATCH 4/9] Update src/skspatial/objects/triangle.py Co-authored-by: Andrew Hynes --- src/skspatial/objects/triangle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skspatial/objects/triangle.py b/src/skspatial/objects/triangle.py index e405071d..bbfc0d74 100644 --- a/src/skspatial/objects/triangle.py +++ b/src/skspatial/objects/triangle.py @@ -529,7 +529,7 @@ def orthocenter(self, tol: np.float64 = None) -> Point: line_alt_a = self.altitude('A') line_alt_b = self.altitude('B') - return line_alt_a.intersect_line(line_alt_b, tol=tol, abs_tol=tol) if tol is not None else line_alt_a.intersect_line(line_alt_b) + return line_alt_a.intersect_line(line_alt_b, **kwargs) def classify(self, **kwargs: float) -> str: """ From 1e6f7dc0828de9d1e4dd793ad07e354fa01502b3 Mon Sep 17 00:00:00 2001 From: volkoshkursk Date: Sun, 27 Nov 2022 15:10:30 +0300 Subject: [PATCH 5/9] Fix: rewrite docs, functions && add tests --- src/skspatial/__init__.py | 2 +- src/skspatial/objects/line.py | 2 +- src/skspatial/objects/line_segment.py | 8 ++++---- src/skspatial/objects/triangle.py | 7 +++---- tests/unit/objects/test_line.py | 18 ++++++++++-------- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/skspatial/__init__.py b/src/skspatial/__init__.py index 6d3c9dfb..ac05c903 100644 --- a/src/skspatial/__init__.py +++ b/src/skspatial/__init__.py @@ -9,4 +9,4 @@ except ModuleNotFoundError: import importlib_metadata # type: ignore -__version__ = importlib_metadata.version("scikit-spatial") +# __version__ = importlib_metadata.version("scikit-spatial") diff --git a/src/skspatial/objects/line.py b/src/skspatial/objects/line.py index aab43847..a743d4db 100644 --- a/src/skspatial/objects/line.py +++ b/src/skspatial/objects/line.py @@ -562,7 +562,7 @@ def intersect_line(self, other: Line, check_coplanar: bool = True, **kwargs) -> if self.direction.is_parallel(other.direction, **kwargs): raise ValueError("The lines must not be parallel.") - if not self.is_coplanar(other, tol=tol): + if check_coplanar and not self.is_coplanar(other): raise ValueError("The lines must be coplanar.") # Vector from line A to line B. diff --git a/src/skspatial/objects/line_segment.py b/src/skspatial/objects/line_segment.py index 3506a867..db346bd5 100644 --- a/src/skspatial/objects/line_segment.py +++ b/src/skspatial/objects/line_segment.py @@ -106,7 +106,7 @@ def contains_point(self, point: array_like, **kwargs) -> bool: return math.isclose(similarity, -1, **kwargs) - def intersect_line_segment(self, other: LineSegment, tol: np.float64 = None) -> Point: + def intersect_line_segment(self, other: LineSegment, **kwargs) -> Point: """ Intersect the line segment with another. @@ -114,9 +114,9 @@ def intersect_line_segment(self, other: LineSegment, tol: np.float64 = None) -> ---------- other : LineSegment - tol : np.float64, optional - Threshold below which values are considered zero. This value is passed to is_coplanar as tol and to is_collinear as abs_tol. - + kwargs : dict, optional + Additional keyword arguments passed to :meth:`Line.intersect_line`. + Returns ------- Point diff --git a/src/skspatial/objects/triangle.py b/src/skspatial/objects/triangle.py index bbfc0d74..17283571 100644 --- a/src/skspatial/objects/triangle.py +++ b/src/skspatial/objects/triangle.py @@ -498,7 +498,7 @@ def altitude(self, vertex: str) -> Line: raise ValueError("The vertex must be 'A', 'B', or 'C'.") - def orthocenter(self, tol: np.float64 = None) -> Point: + def orthocenter(self, **kwargs) -> Point: """ Return the orthocenter of the triangle. @@ -506,9 +506,8 @@ def orthocenter(self, tol: np.float64 = None) -> Point: Parameters ---------- - tol : np.float64, optional - Threshold below which values are considered zero. This value is passed to is_coplanar as tol and to is_collinear as abs_tol. - + kwargs : dict, optional + Additional keywords passed to :meth:`Line.intersect_line`. Returns ------- diff --git a/tests/unit/objects/test_line.py b/tests/unit/objects/test_line.py index 5cdb18f7..19c25d9a 100644 --- a/tests/unit/objects/test_line.py +++ b/tests/unit/objects/test_line.py @@ -213,18 +213,20 @@ def test_distance_line(line_a, line_b, dist_expected): @pytest.mark.parametrize( - ("line_a", "line_b", "array_expected"), + ("line_a", "line_b", "array_expected", "check_coplanar"), [ - (Line([0, 0], [1, 0]), Line([0, 0], [1, 1]), [0, 0]), - (Line([0, 0], [1, 0]), Line([5, 5], [1, 1]), [0, 0]), - (Line([0, 0], [1, 0]), Line([9, 0], [1, 1]), [9, 0]), - (Line([0, 0], [1, 1]), Line([4, 0], [1, -1]), [2, 2]), - (Line([0, 0, 0], [1, 1, 1]), Line([4, 4, 0], [-1, -1, 1]), [2, 2, 2]), + (Line([0, 0], [1, 0]), Line([0, 0], [1, 1]), [0, 0], True), + (Line([0, 0], [1, 0]), Line([5, 5], [1, 1]), [0, 0], True), + (Line([0, 0], [1, 0]), Line([9, 0], [1, 1]), [9, 0], True), + (Line([0, 0], [1, 1]), Line([4, 0], [1, -1]), [2, 2], True), + (Line([0, 0, 0], [1, 1, 1]), Line([4, 4, 0], [-1, -1, 1]), [2, 2, 2], True), + (Line([0, 0, 0], [1, 1, 0]), Line([4, 5, 0], [-1, 0, 0]), [5, 5, 0], True), + (Line([0, 0, 0], [1, 1, 0]), Line([4, 5, 1], [-1, 0, 0]), [5, 5, 0], False), ], ) -def test_intersect_line(line_a, line_b, array_expected): +def test_intersect_line(line_a, line_b, array_expected, check_coplanar): - point_intersection = line_a.intersect_line(line_b) + point_intersection = line_a.intersect_line(line_b, check_coplanar) assert point_intersection.is_close(array_expected) From 869efc0af5cf1c4857b8e14f67738bd904ba103d Mon Sep 17 00:00:00 2001 From: volkoshkursk Date: Mon, 28 Nov 2022 13:03:51 +0300 Subject: [PATCH 6/9] fix: remove test comment. --- src/skspatial/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skspatial/__init__.py b/src/skspatial/__init__.py index ac05c903..6d3c9dfb 100644 --- a/src/skspatial/__init__.py +++ b/src/skspatial/__init__.py @@ -9,4 +9,4 @@ except ModuleNotFoundError: import importlib_metadata # type: ignore -# __version__ = importlib_metadata.version("scikit-spatial") +__version__ = importlib_metadata.version("scikit-spatial") From 4f4a101baa9c697bf8a4f64728f67a49224983fe Mon Sep 17 00:00:00 2001 From: volkoshkursk Date: Thu, 1 Dec 2022 16:01:16 +0300 Subject: [PATCH 7/9] docs: update docs of line.intersect_line. --- src/skspatial/objects/line.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skspatial/objects/line.py b/src/skspatial/objects/line.py index a743d4db..4db8c052 100644 --- a/src/skspatial/objects/line.py +++ b/src/skspatial/objects/line.py @@ -485,8 +485,8 @@ def intersect_line(self, other: Line, check_coplanar: bool = True, **kwargs) -> ---------- other : Line Other line. - tol : np.float64, optional - Threshold below which values are considered zero. This value is passed to is_coplanar + check_coplanar : bool, optional + Check that the lines are coplanar (default True). If False, this method may not return an actual intersection point, but an approximate one. kwargs : dict, optional Additional keywords passed to :meth:`Vector.is_parallel`. From fd785bbe240ba0f41b354857fe9c4591f20a8e68 Mon Sep 17 00:00:00 2001 From: volkoshkursk Date: Tue, 6 Dec 2022 11:22:05 +0300 Subject: [PATCH 8/9] docs: fix docs with respect to E501. --- src/skspatial/objects/line.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/skspatial/objects/line.py b/src/skspatial/objects/line.py index 4db8c052..e399d638 100644 --- a/src/skspatial/objects/line.py +++ b/src/skspatial/objects/line.py @@ -486,7 +486,8 @@ def intersect_line(self, other: Line, check_coplanar: bool = True, **kwargs) -> other : Line Other line. check_coplanar : bool, optional - Check that the lines are coplanar (default True). If False, this method may not return an actual intersection point, but an approximate one. + Check that the lines are coplanar (default True). + If False, this method may not return an actual intersection point, but an approximate one. kwargs : dict, optional Additional keywords passed to :meth:`Vector.is_parallel`. From c2537382eb53e08019db9473bc187ce893a4fd35 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 29 Dec 2022 19:38:32 +0000 Subject: [PATCH 9/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/skspatial/objects/line.py | 2 +- src/skspatial/objects/line_segment.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skspatial/objects/line.py b/src/skspatial/objects/line.py index e399d638..65b0d3a5 100644 --- a/src/skspatial/objects/line.py +++ b/src/skspatial/objects/line.py @@ -486,7 +486,7 @@ def intersect_line(self, other: Line, check_coplanar: bool = True, **kwargs) -> other : Line Other line. check_coplanar : bool, optional - Check that the lines are coplanar (default True). + Check that the lines are coplanar (default True). If False, this method may not return an actual intersection point, but an approximate one. kwargs : dict, optional Additional keywords passed to :meth:`Vector.is_parallel`. diff --git a/src/skspatial/objects/line_segment.py b/src/skspatial/objects/line_segment.py index db346bd5..50cfa42b 100644 --- a/src/skspatial/objects/line_segment.py +++ b/src/skspatial/objects/line_segment.py @@ -116,7 +116,7 @@ def intersect_line_segment(self, other: LineSegment, **kwargs) -> Point: kwargs : dict, optional Additional keyword arguments passed to :meth:`Line.intersect_line`. - + Returns ------- Point