feat(Geometry/Polygon): simple polygons and boundary map#35069
feat(Geometry/Polygon): simple polygons and boundary map#35069A-M-Berns wants to merge 15 commits intoleanprover-community:masterfrom
Conversation
PR summary aac298aee3Import changes for modified filesNo significant changes to the import graph Import changes for all files
|
Mathlib/Geometry/Polygon/Simple.lean
Outdated
| variable (R) in | ||
| /-- A polygon is simple if edges are nondegenerate, non-adjacent edges are disjoint, | ||
| and adjacent edges meet only at their shared vertex. -/ | ||
| def IsSimple (poly : Polygon P n) : Prop := |
There was a problem hiding this comment.
Maybe consider turning this into a structure so you can name each condition?
|
Not necessarily in this PR but should we connect this to https://leanprover-community.github.io/mathlib4_docs/Mathlib/Topology/Path.html#Path in some way? |
My next PR will prove the map is continuous, and then I think the connection to Path wouldn't be hard from there although idk how valuable it would be |
c0194d1 to
a91c05f
Compare
| variable (R) in | ||
| /-- A polygon is simple if edges are nondegenerate, non-adjacent edges are disjoint, | ||
| and adjacent edges meet only at their shared vertex. -/ | ||
| structure IsSimple (poly : Polygon P n) : Prop where |
There was a problem hiding this comment.
Why does this need its own file? Can we put this in the Boundary file, and move later if needed?
There was a problem hiding this comment.
Like I mentioned in the PR description, I think there are results about simple polygons that don't have anything to do with the boundary that will come later. For example, the theorem that if n = 3 then the polygon is simple if and only if it HasNondegenerateVertices.
| variable (R) in | ||
| /-- The boundary parametrization on `R` formed by concatenating edges using `edgePath`. -/ | ||
| noncomputable def boundaryParam (poly : Polygon P n) (t : R) : P := | ||
| let i : Fin n := ⟨(Int.floor t).toNat % n, Nat.mod_lt _ (Nat.pos_of_neZero n)⟩ |
There was a problem hiding this comment.
What about this?
| let i : Fin n := ⟨(Int.floor t).toNat % n, Nat.mod_lt _ (Nat.pos_of_neZero n)⟩ | |
| let i : Fin n := .ofNat (.floor t) |
There was a problem hiding this comment.
Making this suggestion directly creates a bunch of typeclass errors
There was a problem hiding this comment.
maybe my dot notation was wrong, I meant Fin.ofNat (Nat.floor t)
There was a problem hiding this comment.
That gives me the same errors, first complaining about FloorSemiring R and then about NeZero \lfloor t \rfloor
|
This pull request has conflicts, please merge |
5aaa044 to
78046cf
Compare
4f5e0dc to
0378ee4
Compare
This reverts commit f1075e1.
429fb9c to
af9f995
Compare
|
The theorem |
|
This PR/issue depends on: |
|
I suspect we must be missing some kind of API about paths. The boundary of a polygon is intuitively just "all the edge paths concatenated together", not some weird operation involving floors and moduli. What about adding an unbundled version of Path.concat (one without the continuity assumptions), adding whatever relevant API there is to it, and redefine the boundary map of a polygon by using it? |
| /-- A map from `AddCircle n` to the boundary points of the polygon. -/ | ||
| noncomputable def boundaryMap (poly : Polygon P n) : AddCircle (n : R) → P := | ||
| let boundaryParam : R → P := fun t => | ||
| let i : Fin n := ⟨(Int.floor t).toNat % n, Nat.mod_lt _ (Nat.pos_of_neZero n)⟩ |
There was a problem hiding this comment.
I think perhaps this is worth extracting as AddCircle.floor : AddCircle (n : R) -> Fin n?
I think one difference is that Path has distinct endpoints, whereas here we explicitly want wraparound behavior. |
|
What I'm arguing for here is rather some other type |
|
t-euclidean-geometry |
|
@vihdzp I think your proposed design is more elegant but it's at least a full separate PR worth of missing infrastructure plus a complete refactor of this PR. My opinion is that the most important results about the boundaryMap are the ones already in the file, so the work that builds on top of this to e.g. define polygon interiors will not care greatly about the internals of boundaryMap. I would prefer for this PR to still be merged with that refactor as a planned change later, but if others agree that the current definition is too inelegant for mathlib I would be happy to take direction. |
|
I would rather not add tech debt upon ourselves. Mathlib isn't just about proving things, but building good infrastructure. |
|
Personally I don't think it's really tech debt when the refactor would be mostly about elegance and this is a functional API surface as is especially for the obvious things that will depend on this boundaryMap, but again I'd like to hear others' thoughts. |
|
I agree with the previous comments that some general API for joining paths together at their endpoints would be an appropriate basis for this PR (I haven't checked whether any such API already exists). |
This PR introduces Simple polygons with the predicate
IsSimple, which captures the idea of a non-self-intersecting boundary, in the file Simple.lean. In the file Boundary.lean, a boundary map fromAddCircle nis defined. I prove that the range of this map is the boundary and that this map is injective if and only if the polygon is simple. I kept Boundary.lean and Simple.lean separate because future results will include stuff just about the boundary map independent of simplicity (e.g. that it is continuous in the appropriate setting) and stuff just about simple polygons independent of the boundary map (e.g. that for n = 3, IsSimple iff HasNondegenerateVertices.) I used Claude Code to help generate some of the proof material, but I golfed and edited all AI contribution.