diff --git a/CMakeLists.txt b/CMakeLists.txt index 68d0368..cc814dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ install(DIRECTORY "include" DESTINATION ".") add_library(${PROJECT_NAME} SHARED "src/angle/angle.cpp" + "src/geometry/line.cpp" "src/geometry/point_2.cpp" "src/geometry/point_3.cpp" "src/matrix/matrix.cpp" diff --git a/include/keisan/geometry/line.hpp b/include/keisan/geometry/line.hpp new file mode 100644 index 0000000..ec1de4c --- /dev/null +++ b/include/keisan/geometry/line.hpp @@ -0,0 +1,51 @@ +// Copyright (c) 2026 ICHIRO ITS +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef KEISAN__GEOMETRY__LINE_HPP_ +#define KEISAN__GEOMETRY__LINE_HPP_ + +#include "keisan/geometry/point_2.hpp" + +namespace keisan +{ + +struct Line +{ + Line(); + Line(double a, double b, double c); + + static Line from_points(const Point2 & p1, const Point2 & p2); + static Line from_point(const Point2 & point, const Angle & angle); + + double distance(const Point2 & point) const; + + std::optional slope() const; + Angle angle() const; + + std::optional intersection(const Line & other) const; + + double a; + double b; + double c; +}; + +} // namespace keisan + +#endif // KEISAN__GEOMETRY__LINE_HPP_ \ No newline at end of file diff --git a/src/geometry/line.cpp b/src/geometry/line.cpp new file mode 100644 index 0000000..316623e --- /dev/null +++ b/src/geometry/line.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2026 ICHIRO ITS +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "keisan/geometry/line.hpp" + +namespace keisan +{ + +Line::Line() {} + +Line::Line(double a, double b, double c) : a(a), b(b), c(a) {} + +Line Line::from_points(const Point2 & p1, const Point2 & p2) +{ + double a = p2.y - p1.y; + double b = p1.x - p2.x; + double c = -(a * p1.x + b * p1.y); + return Line(a, b, c); +} + +Line Line::from_point(const Point2 & point, const Angle & angle) +{ + double a = -angle.sin(); + double b = angle.cos(); + double c = -(a * point.x + b * point.y); + + return Line(a, b, c); +} + +double Line::distance(const Point2 & point) const +{ + double denominator = std::hypot(a, b); + + if (denominator < 1e-9) { + throw std::runtime_error( + "Invalid line equations: coefficients 'a' and 'b' cannot both be zero."); + } + + return std::abs(a * point.x + b * point.y + c) / denominator; +} + +std::optional Line::intersection(const Line & other) const +{ + double determinant = a * other.b - other.a * b; + if (std::abs(determinant) < 1e-9) { + return std::nullopt; // Lines are parallel or coincident + } + double x = (b * other.c - other.b * c) / determinant; + double y = (other.a * c - a * other.c) / determinant; + return Point2{x, y}; +} + +std::optional Line::slope() const +{ + if (std::abs(b) < 1e-9) return std::nullopt; // Line is vertical + return -a / b; +} + +Angle Line::angle() const { return signed_arctan(a, -b); } + +} // namespace keisan \ No newline at end of file