Skip to content

Instantly share code, notes, and snippets.

@aj-fleming
Created September 12, 2025 11:48
Show Gist options
  • Select an option

  • Save aj-fleming/7e5ae49126339e79b2154b1a31b9423d to your computer and use it in GitHub Desktop.

Select an option

Save aj-fleming/7e5ae49126339e79b2154b1a31b9423d to your computer and use it in GitHub Desktop.
module PlanePolygons_MWE
using StaticArrays
using LinearAlgebra
export SClosedPolygon, edge_starts
# Absolute tolerance threshold.
const _HOW_CLOSE_IS_TOO_CLOSE = 1.0e-12
# Represents a Line in ℝ^2
struct Line{T}
p::SVector{2,T}
dir::SVector{2,T}
end
# get a point on a line
point_on(ℓ) =.p
# get the direction of a line
direction_of(ℓ) =.dir
# get a vector that points into the right half-plane defined by ℓ
# from any point on ℓ
function right_normal(ℓ)
dir = direction_of(ℓ)
return SVector(dir[2], -dir[1])
end
# Helper method for testing if a point is to the right of ℓ
function _right_half_plane(ℓ, pt)
v1 = right_normal(ℓ) pt
v2 = right_normal(ℓ) point_on(ℓ)
return (v1, v2)
end
# Test if a point is to the right of ℓ but NOT on ℓ
function point_in_right_half_plane_strict(ℓ, pt)
(v1, v2) = _right_half_plane(ℓ, pt)
return v1 > v2 && !isapprox(v1 - v2, 0; atol=_HOW_CLOSE_IS_TOO_CLOSE)
end
# Represents a closed, clockwise-oriented polygon as an SVector{NV} of SVectors{2, T}
struct SClosedPolygon{NV,T}
pts::SVector{NV,SVector{2,T}}
end
function SClosedPolygon(pts::Vararg{SVector{2,T}}) where {T}
return SClosedPolygon(SVector(pts...))
end
# get an iterator that traverses the first point on each edge in order
function edge_starts(p::SClosedPolygon)
return p.pts
end
# get an iterator that traverses the second point on each edge in order
function edge_ends(p::SClosedPolygon{NV,T}) where {NV,T}
return p.pts[SVector(ntuple(i -> i + 1, NV - 1)..., 1)]
end
# get an iterator of lines coincendent with each edge of `poly` in order
function edge_lines(poly::SClosedPolygon{NV}) where {NV}
return mapreduce(vcat, edge_starts(poly), edge_ends(poly)) do a, b
return SVector(Line(a, b - a))
end
end
# Test if a point is strictly inside a polygon
# Base.Fix2 might be the issue here?
function point_inside_strict(poly, pt)
return all(Base.Fix2(point_in_right_half_plane_strict, pt), edge_lines(poly))
end
end
# Stripped-down version of Euler2D to reproduce the compiler bug(?).
module Euler2D_MWE
using StaticArrays
using ..PlanePolygons_MWE
export TangentQuadCell_MWE, cell_boundary_polygon
# Analagous to the original code in Euler2D.
abstract type FVMCell{T} end
# Analagous to the original code in Euler2D.
struct TangentQuadCell_MWE{T,NSEEDS,NTANGENTS} <: FVMCell{T}
id::Int
u::SVector{4,T}
udot::SMatrix{4,NSEEDS,T,NTANGENTS}
center::SVector{2,T}
extent::SVector{2,T}
end
# Given a cell, which has a center and extent, produce the clockwise-oriented polygon that is its boundary.
function cell_boundary_polygon(cell::TangentQuadCell_MWE)
dx, dy = cell.extent / 2
return SClosedPolygon(
cell.center + SVector(dx, -dy),
cell.center + SVector(-dx, -dy),
cell.center + SVector(-dx, dy),
cell.center + SVector(dx, dy)
)
end
# Test if a cell's boundary polygon is completely contained by some other polygon.
function is_cell_contained_by(cell1, poly)
cell_poly = cell_boundary_polygon(cell1)
return all(edge_starts(cell_poly)) do pt
return PlanePolygons_MWE.point_inside_strict(poly, pt)
end
end
# behavior is reproducible with or without second method definition.
# function is_cell_contained_by(cell1, cell2::FVMCell)
# return is_cell_contained_by(cell1, cell_boundary_polygon(cell2))
# end
end
# METHOD TO REPRODUCE
# (works at the REPL)
# using StaticArrays, BenchmarkTools
# using .PlanePolygons_MWE, .Euler2D_MWE
# test_poly1 = SClosedPolygon(@SVector([SVector(-1.3, 1.5), SVector(-1.4, 1.5), SVector(-1.4, 1.75), SVector(-1.3, 1.75)]))
# test_cell = TangentQuadCell_MWE(1, SVector(1.0, 4.0, 0.0, 9.87), SMatrix{4,3}(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0), SVector(-1.49687, 0.03125), SVector(0.00625, 0.00625))
# should yield allocations (6 allocs / 544 bytes on my machine)
# @benchmark Euler2D_MWE.is_cell_contained_by($test_cell, $test_poly1)
# resident eval
# @eval Euler2D_MWE function is_cell_contained_by(cell1, poly)
# cell_poly = cell_boundary_polygon(cell1)
# return all(edge_starts(cell_poly)) do pt
# return PlanePolygons_MWE.point_inside_strict(poly, pt)
# end
# end
# benchmark again, should yield no allocs and ~4x speedup
# @benchmark Euler2D_MWE.is_cell_contained_by($test_cell, $test_poly1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment