-
Notifications
You must be signed in to change notification settings - Fork 0
Port 2D geometry module #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis pull request integrates a new module for 2D geometry into the codebase. The Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant SM as SpatialMath Module
participant G2D as Geometry2D Module
participant L2 as Line2 Instance
participant P2 as Polygon2 Instance
participant Test as Test Suite
User->>SM: Executes spatial functions
SM->>G2D: Include and invoke 2D geometry operations
User->>G2D: Calls join_points(p1, p2)
G2D-->>L2: Constructs Line2 using cross product
User->>G2D: Calls general_line(m, c)
G2D-->>L2: Constructs Line2 using slope-intercept form
User->>G2D: Creates Polygon2 with vertices
G2D-->>P2: Constructs Polygon2 instance
Test->>G2D: Executes tests on Line2 functionality
Test->>G2D: Executes tests on Polygon2 functionality
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (4)
src/geometry2d.jl (4)
7-11: Add documentation for the Line2 struct.The struct is well-designed with type parameterization and appropriate inheritance. Consider adding documentation to explain:
- The mathematical representation (ax + by + c = 0)
- The purpose of type parameter T
- Usage examples
+""" + Line2{T} <: AbstractVector{T} + +Represents a 2D line in homogeneous coordinates using the equation ax + by + c = 0. +Type parameter T allows for different numeric types (e.g., Float64, Rational). + +# Examples +```julia +# Create a line passing through points [0,0] and [1,1] +l = join_points([0,0], [1,1]) +``` +""" struct Line2{T} <: AbstractVector{T}
16-18: Simplify getindex implementation.The Base method implementations look good, but the getindex implementation could be simplified using tuple indexing.
-Base.getindex(l::Line2, i::Int) = i == 1 ? l.a : i == 2 ? l.b : l.c +Base.getindex(l::Line2, i::Int) = getfield(l, (:a, :b, :c)[i])
20-32: Fix error message typos and enhance documentation.The implementation is mathematically correct, but there are some improvements needed:
- Fix grammar in error messages
- Add detailed documentation explaining the mathematical operation
+""" + join_points(p1::AbstractVector{T}, p2::AbstractVector{S})::Line2 + +Create a line passing through two points using their cross product. +Points can be specified in either 2D [x,y] or homogeneous [x,y,w] coordinates. + +# Arguments +- `p1`: First point as [x,y] or [x,y,w] +- `p2`: Second point as [x,y] or [x,y,w] + +# Returns +- `Line2`: Line passing through p1 and p2 + +# Examples +```julia +l = join_points([0,0], [1,1]) # Line through origin and (1,1) +``` +""" function join_points( p1::AbstractVector{T}, p2::AbstractVector{S}, )::Line2 where {T<:Number,S<:Number} length(p1) in (2, 3) || - throw(DimensionMismatch("p1 must has homogeneous line representation: ax + by + c = 0")) + throw(DimensionMismatch("p1 must have homogeneous line representation: ax + by + c = 0")) length(p2) in (2, 3) || - throw(DimensionMismatch("p2 must has homogeneous line representation: ax + by + c = 0")) + throw(DimensionMismatch("p2 must have homogeneous line representation: ax + by + c = 0"))
34-40: Enhance documentation and add parameter validation.The implementation is correct, but consider:
- Adding examples to documentation
- Adding validation for special cases (e.g., vertical lines)
""" general_line(m::Number, c::Number) - Creates a line from the parameters of the general line `y = mx + c`. +Creates a line from the parameters of the general line `y = mx + c`. + +# Arguments +- `m`: Slope of the line +- `c`: Y-intercept + +# Returns +- `Line2`: Line in the form mx - y + c = 0 + +# Examples +```julia +l1 = general_line(1, 0) # y = x +l2 = general_line(2, -1) # y = 2x - 1 +``` """ function general_line(m::Number, c::Number)::Line2 + isfinite(m) || throw(DomainError(m, "Slope must be finite")) return Line2(m, -1, c) end
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/SpatialMath.jl(1 hunks)src/geometry2d.jl(1 hunks)test/test-line2-test.jl(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/SpatialMath.jl
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: test / Julia 1 - ubuntu-latest - x64 - pull_request
- GitHub Check: Documentation
- GitHub Check: Linting
🔇 Additional comments (1)
src/geometry2d.jl (1)
1-4: LGTM!Good module organization with specific import of the required functionality.
| Line2(v) = Line2(v...) | ||
| Line2(a, b, c) = Line2(a, b, c) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add input validation to constructors.
The vector constructor could be unsafe without length validation. Consider:
- Adding length validation
- Removing the redundant three-parameter constructor
-Line2(v) = Line2(v...)
-Line2(a, b, c) = Line2(a, b, c)
+"""
+ Line2(v)
+
+Construct a Line2 from a vector of 3 elements [a,b,c].
+"""
+function Line2(v)
+ length(v) == 3 || throw(DimensionMismatch("Line2 requires 3 parameters"))
+ Line2(v...)
+end📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Line2(v) = Line2(v...) | |
| Line2(a, b, c) = Line2(a, b, c) | |
| """ | |
| Line2(v) | |
| Construct a Line2 from a vector of 3 elements [a,b,c]. | |
| """ | |
| function Line2(v) | |
| length(v) == 3 || throw(DimensionMismatch("Line2 requires 3 parameters")) | |
| Line2(v...) | |
| end |
| using Test | ||
| using SpatialMath.Geometry2D | ||
|
|
||
| @testset "Line2" begin | ||
| @testset "constructor" begin | ||
| l = Line2([1, 2, 3]) | ||
| @test repr(l) == "Line2(1, 2, 3)" | ||
|
|
||
| l = Geometry2D.join_points([0, 0], [1, 2]) | ||
| @test vec(l) == [-2, 1, 0] | ||
|
|
||
| l = Geometry2D.general_line(2, 1) | ||
| @test vec(l) == [2, -1, 1] | ||
| end | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add more test cases for comprehensive coverage.
While the basic functionality is tested, consider adding tests for:
- Error conditions (invalid dimensions, infinite slopes)
- Edge cases (vertical lines, parallel lines)
- Different numeric types (Float64, Rational)
@testset "Line2" begin
@testset "constructor" begin
l = Line2([1, 2, 3])
@test repr(l) == "Line2(1, 2, 3)"
l = Geometry2D.join_points([0, 0], [1, 2])
@test vec(l) == [-2, 1, 0]
l = Geometry2D.general_line(2, 1)
@test vec(l) == [2, -1, 1]
+
+ # Test error conditions
+ @test_throws DimensionMismatch Line2([1, 2])
+ @test_throws DimensionMismatch Geometry2D.join_points([0], [1])
+
+ # Test edge cases
+ l = Geometry2D.join_points([0, 0], [0, 1]) # Vertical line
+ @test vec(l) == [1, 0, 0]
+
+ # Test different numeric types
+ l = Line2(Rational{Int}[1, 2, 3])
+ @test eltype(l) == Rational{Int}
end
end📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| using Test | |
| using SpatialMath.Geometry2D | |
| @testset "Line2" begin | |
| @testset "constructor" begin | |
| l = Line2([1, 2, 3]) | |
| @test repr(l) == "Line2(1, 2, 3)" | |
| l = Geometry2D.join_points([0, 0], [1, 2]) | |
| @test vec(l) == [-2, 1, 0] | |
| l = Geometry2D.general_line(2, 1) | |
| @test vec(l) == [2, -1, 1] | |
| end | |
| end | |
| using Test | |
| using SpatialMath.Geometry2D | |
| @testset "Line2" begin | |
| @testset "constructor" begin | |
| l = Line2([1, 2, 3]) | |
| @test repr(l) == "Line2(1, 2, 3)" | |
| l = Geometry2D.join_points([0, 0], [1, 2]) | |
| @test vec(l) == [-2, 1, 0] | |
| l = Geometry2D.general_line(2, 1) | |
| @test vec(l) == [2, -1, 1] | |
| # Test error conditions | |
| @test_throws DimensionMismatch Line2([1, 2]) | |
| @test_throws DimensionMismatch Geometry2D.join_points([0], [1]) | |
| # Test edge cases | |
| l = Geometry2D.join_points([0, 0], [0, 1]) # Vertical line | |
| @test vec(l) == [1, 0, 0] | |
| # Test different numeric types | |
| l = Line2(Rational{Int}[1, 2, 3]) | |
| @test eltype(l) == Rational{Int} | |
| end | |
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (5)
test/test-line2-test.jl (2)
16-22: Add edge cases to point containment tests.Consider adding tests for:
- Points on vertical lines
- Points with different numeric types
- Points with homogeneous coordinates
@testset "contains" begin l = join_points([0, 0], [1, 2]) @test Geometry2D.contains(l, [0, 0]) @test Geometry2D.contains(l, [1, 2]) @test Geometry2D.contains(l, [2, 4]) @test !Geometry2D.contains(l, [1, 1]) + + # Test vertical line + l = join_points([2, 0], [2, 1]) + @test Geometry2D.contains(l, [2, 0]) + @test Geometry2D.contains(l, [2, 1]) + @test !Geometry2D.contains(l, [1, 0]) + + # Test different numeric types + @test Geometry2D.contains(l, Float64[2, 0]) + + # Test homogeneous coordinates + @test Geometry2D.contains(l, [2, 0, 1]) end
24-31: Add more intersection test cases.Consider adding tests for:
- Lines that intersect at non-right angles
- Lines with different numeric types
- Edge cases (coincident lines)
@testset "intersection" begin l1 = join_points([0, 0], [2, 0]) # x-axis l2 = join_points([0, 1], [2, 1]) # y = 1 @test !Geometry2D.intersect(l1, l2) l2 = join_points([2, 1], [2, -1]) # x = 2 @test Geometry2D.intersect(l1, l2) + + # Test non-right angle intersection + l2 = join_points([0, 0], [1, 1]) # y = x + @test Geometry2D.intersect(l1, l2) + + # Test different numeric types + l2 = Line2(Float64[1, 1, 0]) # y = -x + @test Geometry2D.intersect(l1, l2) + + # Test coincident lines + l2 = join_points([1, 0], [3, 0]) # x-axis + @test !Geometry2D.intersect(l1, l2) endsrc/geometry2d.jl (3)
16-18: Improve getindex implementation.Consider:
- Adding bounds checking
- Using pattern matching for better readability
Base.show(io::IO, l::Line2) = print(io, "Line2($(l.a), $(l.b), $(l.c))") Base.size(::Line2) = (3,) -Base.getindex(l::Line2, i::Int) = i == 1 ? l.a : i == 2 ? l.b : l.c +function Base.getindex(l::Line2, i::Int) + 1 <= i <= 3 || throw(BoundsError(l, i)) + return @match i begin + 1 => l.a + 2 => l.b + 3 => l.c + end +end
20-32: Improve error messages and add documentation.Consider:
- Making error messages more descriptive
- Adding documentation with examples
+""" + join_points(p1::AbstractVector, p2::AbstractVector)::Line2 + +Create a line passing through two points. Points can be given in 2D [x,y] or +homogeneous [x,y,w] coordinates. + +# Examples +```julia +l = join_points([0, 0], [1, 1]) # Line y = x +l = join_points([0, 0, 1], [1, 1, 1]) # Same line in homogeneous coordinates +``` +""" function join_points( p1::AbstractVector{T}, p2::AbstractVector{S}, )::Line2 where {T<:Number,S<:Number} length(p1) in (2, 3) || - throw(DimensionMismatch("p1 must has homogeneous line representation: ax + by + c = 0")) + throw(DimensionMismatch("p1 must be a 2D point [x,y] or homogeneous point [x,y,w]")) length(p2) in (2, 3) || - throw(DimensionMismatch("p2 must has homogeneous line representation: ax + by + c = 0")) + throw(DimensionMismatch("p2 must be a 2D point [x,y] or homogeneous point [x,y,w]")) _p1 = length(p1) == 2 ? vcat(p1, 1) : p1 _p2 = length(p2) == 2 ? vcat(p2, 1) : p2 return Line2(cross(_p1, _p2)) end
38-44: Add documentation and tolerance parameter.Consider:
- Adding documentation with examples
- Adding a tolerance parameter for approximate equality
+""" + contains(l::Line2, p::AbstractVector; atol::Real=0)::Bool + +Check if a point lies on a line. Points can be given in 2D [x,y] or +homogeneous [x,y,w] coordinates. + +# Examples +```julia +l = join_points([0, 0], [1, 1]) # y = x +@assert contains(l, [2, 2]) # Point on line +@assert !contains(l, [1, 0]) # Point off line +``` +""" -function contains(l::Line2, p::AbstractVector{T}) where {T<:Number} +function contains(l::Line2, p::AbstractVector{T}; atol::Real=0) where {T<:Number} length(p) in (2, 3) || - throw(DimensionMismatch("p must has homogeneous line representation: ax + by + c = 0")) + throw(DimensionMismatch("p must be a 2D point [x,y] or homogeneous point [x,y,w]")) _p = length(p) == 2 ? vcat(p, 1) : p - return dot(l, _p) ≈ 0 + return isapprox(dot(l, _p), 0; atol=atol) end
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/geometry2d.jl(1 hunks)test/test-line2-test.jl(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Documentation
🔇 Additional comments (2)
test/test-line2-test.jl (1)
5-14: Add more test cases for comprehensive coverage.While the basic functionality is tested, consider adding tests for:
- Error conditions (invalid dimensions)
- Edge cases (vertical lines, parallel lines)
- Different numeric types (Float64, Rational)
@testset "constructor" begin l = Line2([1, 2, 3]) @test repr(l) == "Line2(1, 2, 3)" l = join_points([0, 0], [1, 2]) @test vec(l) == [-2, 1, 0] l = general_line(2, 1) @test vec(l) == [2, -1, 1] + + # Test error conditions + @test_throws DimensionMismatch Line2([1, 2]) + @test_throws DimensionMismatch join_points([0], [1]) + + # Test edge cases + l = join_points([0, 0], [0, 1]) # Vertical line + @test vec(l) == [1, 0, 0] + + # Test different numeric types + l = Line2(Rational{Int}[1, 2, 3]) + @test eltype(l) == Rational{Int} endsrc/geometry2d.jl (1)
7-14: Add input validation and documentation to constructors.The vector constructor could be unsafe without length validation. Consider:
- Adding length validation
- Adding documentation
- Adding type promotion for mixed numeric types
struct Line2{T} <: AbstractVector{T} a::T b::T c::T end -Line2(v) = Line2(v...) -Line2(a, b, c) = Line2(a, b, c) +""" + Line2(v) + +Construct a Line2 from a vector of 3 elements [a,b,c]. +""" +function Line2(v) + length(v) == 3 || throw(DimensionMismatch("Line2 requires 3 parameters")) + T = promote_type(map(typeof, v)...) + Line2(convert(Vector{T}, v)...) +end + +""" + Line2(a, b, c) + +Construct a Line2 from coefficients a, b, c representing ax + by + c = 0. +""" +function Line2(a::Number, b::Number, c::Number) + T = promote_type(typeof(a), typeof(b), typeof(c)) + Line2(convert(T, a), convert(T, b), convert(T, c)) +end
| function general_line(m::Number, c::Number)::Line2 | ||
| return Line2(m, -1, c) | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add documentation and handle vertical lines.
Consider:
- Adding documentation with examples
- Adding a special case for vertical lines (infinite slope)
+"""
+ general_line(m::Number, c::Number)::Line2
+
+Create a line from slope-intercept form y = mx + c.
+For vertical lines, use `join_points([x₀, y₁], [x₀, y₂])` instead.
+
+# Examples
+```julia
+l = general_line(1, 0) # y = x
+l = general_line(0, 1) # y = 1
+```
+"""
function general_line(m::Number, c::Number)::Line2
+ isfinite(m) || throw(DomainError(m, "Slope must be finite"))
return Line2(m, -1, c)
end| function intersect(l1::Line2, l2::Line2) | ||
| c = cross(l1, l2) | ||
| return abs(c[end]) > 0 | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add documentation and enhance intersection functionality.
Consider:
- Adding documentation with examples
- Adding a tolerance parameter for approximate equality
- Adding an option to return the intersection point
+"""
+ intersect(l1::Line2, l2::Line2; atol::Real=0, return_point::Bool=false)
+
+Check if two lines intersect. Optionally returns the intersection point.
+
+# Examples
+```julia
+l1 = join_points([0, 0], [1, 0]) # x-axis
+l2 = join_points([0, 0], [0, 1]) # y-axis
+@assert intersect(l1, l2) # Lines intersect
+p = intersect(l1, l2, return_point=true) # Get intersection point [0, 0]
+```
+"""
-function intersect(l1::Line2, l2::Line2)
+function intersect(l1::Line2, l2::Line2; atol::Real=0, return_point::Bool=false)
c = cross(l1, l2)
- return abs(c[end]) > 0
+ has_intersection = !isapprox(abs(c[end]), 0; atol=atol)
+ if !return_point
+ return has_intersection
+ end
+ has_intersection || throw(ArgumentError("Lines do not intersect"))
+ return [-c[1]/c[3], -c[2]/c[3]]
endAdd: Polygon2, area, bbox, centroid, edges, moment, radius, vertices Missing: transform, intersect, intersect_line They rely on the transformation object which I haven't ported yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (3)
test/test-polygon2-test.jl (1)
52-58: Document expected behavior for missing methods.While it's good to mark unimplemented methods with @test_broken, consider adding documentation about the expected behavior of these methods to guide future implementation.
@testset "missing" begin - "FIXME: Polygon2 missing methods" + # FIXME: Implement the following methods: + # - transform: Apply affine transformation to polygon + # - intersect: Check if two polygons intersect + # - intersect_linet: Find intersection points between polygon and line p = Polygon2([(1, 2), (3, 2), (2, 4)]) @test_broken Geometry2D.transform(p) @test_broken Geometry2D.intersect(p) @test_broken Geometry2D.intersect_linet(p, Line2([1, 2]))src/geometry2d.jl (2)
88-127: Optimize moment calculation.Consider these optimizations:
- Cache binomial coefficients for repeated calculations
- Use precomputed factorials for small values
+const MAX_CACHED_FACTORIAL = 20 +const FACTORIALS = [factorial(big(i)) for i in 0:MAX_CACHED_FACTORIAL] + function _binomial(n::Int, k::Int) k < 0 && return 0 k > n && return 0 k = min(k, n - k) - result = 1 - for i = 1:k - result *= (n - i + 1) / i + if n <= MAX_CACHED_FACTORIAL + return Int(FACTORIALS[n+1] ÷ (FACTORIALS[k+1] * FACTORIALS[n-k+1])) end + result = 1 + for i = 1:k + result *= (n - i + 1) / i + end return result end
215-225: Add TODO comments for unimplemented methods.Add documentation explaining the intended behavior of these methods.
+# TODO: Implement polygon-polygon intersection function intersect(p::Polygon2) return false end +# TODO: Implement polygon-line intersection function intersect_line(::Polygon2, ::Line2) return false end +# TODO: Implement affine transformation function transform(::Polygon2) return false end
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/geometry2d.jl(1 hunks)test/test-polygon2-test.jl(1 hunks)
🔇 Additional comments (8)
test/test-polygon2-test.jl (3)
15-26: LGTM! Well-structured test cases for physical properties.The test cases thoroughly verify the physical properties of a square polygon, including area, moments, centroid, radius, and bounding box calculations. The expected values are mathematically correct.
28-41: LGTM! Comprehensive point containment tests.The test cases thoroughly verify the point containment functionality with:
- Interior points
- Points on edges
- Points outside the polygon
- Appropriate precision radius
43-50: LGTM! Edge extraction tests are correct.The test cases properly verify that edges are extracted in order and form a closed polygon by connecting consecutive vertices, including the last vertex back to the first.
src/geometry2d.jl (5)
27-28: Add input validation to constructors.The vector constructor could be unsafe without length validation.
34-46: LGTM! Well-implemented point-to-line conversion.The function properly validates input dimensions, handles both 2D and homogeneous coordinates, and uses the cross product to create the line equation.
48-50: Add documentation and handle vertical lines.The function needs documentation and special handling for vertical lines.
60-63: Add documentation and enhance intersection functionality.The function needs documentation, tolerance parameter, and option to return intersection point.
150-207: LGTM! Robust point containment implementation.The implementation correctly handles:
- Ray casting for basic containment
- Edge proximity with positive radius
- Polygon shrinking with negative radius
| p = Polygon2([(1, 2), (3, 2), (2, 4)]) | ||
| @test p isa Polygon2 | ||
| @test length(p) == 3 | ||
| @test string(p) == "Polygon2 with 4 vertices" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect test expectation.
The test expects "4 vertices" in the string representation but only 3 vertices are provided to the constructor. This appears to be a mismatch between the test expectation and the actual input data.
- @test string(p) == "Polygon2 with 4 vertices"
+ @test string(p) == "Polygon2 with 3 vertices"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @test string(p) == "Polygon2 with 4 vertices" | |
| @test string(p) == "Polygon2 with 3 vertices" |
| function Polygon2(points::Vector{<:Tuple}) | ||
| verts = reduce(hcat, [[x[1], x[2]] for x in points]) | ||
| Polygon2(verts) | ||
| end | ||
|
|
||
| Polygon2(vertices::AbstractMatrix) = Polygon2(vertices) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add input validation to Polygon2 constructors.
The constructors should validate that:
- Points form a valid polygon (at least 3 vertices)
- Matrix has correct dimensions (2×n)
function Polygon2(points::Vector{<:Tuple})
+ length(points) >= 3 || throw(ArgumentError("Polygon must have at least 3 vertices"))
verts = reduce(hcat, [[x[1], x[2]] for x in points])
Polygon2(verts)
end
-Polygon2(vertices::AbstractMatrix) = Polygon2(vertices)
+function Polygon2(vertices::AbstractMatrix)
+ size(vertices, 1) == 2 || throw(DimensionMismatch("Matrix must have 2 rows"))
+ size(vertices, 2) >= 3 || throw(ArgumentError("Polygon must have at least 3 vertices"))
+ Polygon2(vertices)
+end📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function Polygon2(points::Vector{<:Tuple}) | |
| verts = reduce(hcat, [[x[1], x[2]] for x in points]) | |
| Polygon2(verts) | |
| end | |
| Polygon2(vertices::AbstractMatrix) = Polygon2(vertices) | |
| function Polygon2(points::Vector{<:Tuple}) | |
| length(points) >= 3 || throw(ArgumentError("Polygon must have at least 3 vertices")) | |
| verts = reduce(hcat, [[x[1], x[2]] for x in points]) | |
| Polygon2(verts) | |
| end | |
| function Polygon2(vertices::AbstractMatrix) | |
| size(vertices, 1) == 2 || throw(DimensionMismatch("Matrix must have 2 rows")) | |
| size(vertices, 2) >= 3 || throw(ArgumentError("Polygon must have at least 3 vertices")) | |
| Polygon2(vertices) | |
| end |
Summary by CodeRabbit
New Features
Tests
Line2andPolygon2classes, covering constructors, physical properties, point containment, and intersection validations.