LCOV - code coverage report
Current view: top level - src/geometry - statistics.jl (source / functions) Hit Total Coverage
Test: on branch nothing Lines: 49 51 96.1 %
Date: 2025-07-10 13:12:25 Functions: 0 0 -

          Line data    Source code
       1             : 
       2           1 : centroid(m::Mesh, x, f::FHnd) = centroid(geometry(m, x), f)
       3             : 
       4          31 : centroid(g::AbstractGeometry, f::FHnd,) =
       5             :     centroid(g, f, _istriangulation(g))
       6             : 
       7           4 : centroid(g::AbstractGeometry, f::FHnd, :: IsTriangulation) =
       8             :     mean(position(g, v) for v in triangle(tessellation(g), f))
       9             : 
      10          27 : centroid(g::AbstractGeometry, f::FHnd, :: NoTriangulation) =
      11             :     mean(position(g, v) for v in vertices(tessellation(g), f))
      12             : 
      13           1 : centroid(m::Mesh, x) = centroid(geometry(m, x))
      14             : 
      15          13 : function centroid(g::AbstractGeometry)
      16          39 :     function weightedcentroid(f)
      17          26 :         a = facearea(g, f)
      18          26 :         (a * centroid(g, f), a)
      19             :     end
      20             : 
      21          13 :     s = foldl(.+, (weightedcentroid(f) for f in faces(tessellation(g))))
      22             : 
      23          13 :     first(s) / last(s)
      24             : end
      25             : 
      26             : """
      27             :     g = geometry(mesh, x)
      28             : 
      29             :     c = centroid(g, f)
      30             :     c = centroid(mesh, x, f)
      31             : 
      32             :     c = centroid(g)
      33             :     c = centroid(mesh, x)
      34             : 
      35             : Compute centroid of a single face `f` or of the entire surface `g`
      36             : using area-weighted centroids of faces.
      37             : """ centroid
      38             : 
      39           7 : function Statistics.mean(g::AbstractGeometry)
      40           7 :     x = position(g)
      41             : 
      42           7 :     Statistics.mean(x[v] for v in vertices(tessellation(g)))
      43             : end
      44             : 
      45           1 : function Statistics.std(g::AbstractGeometry)
      46           1 :     x = position(g)
      47           1 :     Statistics.std(collect(x[v] for v in vertices(tessellation(g)));
      48             :                    corrected=false)
      49             : end
      50             : 
      51           1 : function Statistics.cov(g::AbstractGeometry)
      52           1 :     x = position(g)
      53           1 :     Statistics.cov(collect(x[v] for v in vertices(tessellation(g)));
      54             :                    corrected=false)
      55             : end
      56             : 
      57             : """
      58             :     g = geometry(mesh, x)
      59             :     centercentroid!(g)
      60             : 
      61             :     @assert centroid(g) ≈ zeros(eltype(position(g)))
      62             : 
      63             :     centercentroid!(g; origin = z)
      64             : 
      65             :     @assert centroid(g) ≈ z
      66             : 
      67             : Shift vertex positions such that [`centroid`]@(ref) is located in the
      68             : `origin`.
      69             : 
      70             : See also [`centroid`]@(ref), [`centermean!`](@ref)
      71             : """
      72           4 : function centercentroid!(g::AbstractGeometry;
      73             :                          origin = zeros(eltype(position(g))))
      74           2 :     x = position(g)
      75           2 :     c = centroid(g) - origin
      76             : 
      77           4 :     for v in vertices(tessellation(g))
      78          12 :         x[v] = x[v] - c
      79          12 :     end
      80             : 
      81           0 :     nothing
      82             : end
      83             : 
      84             : """
      85             :     g = geometry(mesh, x)
      86             :     centermean!(g)
      87             : 
      88             :     @assert Statistics.mean(g) ≈ zeros(eltype(position(g)))
      89             : 
      90             :     centermean!(g; origin = z)
      91             : 
      92             :     @assert Statistics.mean(g) ≈ z
      93             : 
      94             : Shift vertex positions such that `Statistics.mean` is located in the
      95             : `origin`.
      96             : 
      97             : See also [`mean`]@(ref), [`centercentroid!`](@ref)
      98             : """
      99           4 : function centermean!(g::AbstractGeometry; origin = zeros(eltype(position(g))))
     100           2 :     x = position(g)
     101           2 :     c = Statistics.mean(g) - origin
     102             : 
     103           4 :     for v in vertices(tessellation(g))
     104          12 :         x[v] = x[v] - c
     105          12 :     end
     106             : 
     107           0 :     nothing
     108             : end
     109             : 
     110             : 
     111             : """
     112             :     g = geometry(mesh, x)
     113             :     U, λ, center = pca(mesh[; centroids=false])
     114             : 
     115             : Compute Principle Component Analysis of either `position(g)` or
     116             : [`centroid`](@ref)s (`centroids=true`).
     117             : 
     118             : Compute the covariance matrix `C = (X .- center)'*(X .- center) / n`,
     119             : such that
     120             : 
     121             :     C = U * Diagonal(λ) * U'
     122             : 
     123             : with nonnegative eigenvalues `λ`. Here, `n` equals the number of
     124             : vertices or the number of faces (`centroids=true`), and `center`
     125             : equals the `mean` or the [`centroid`](@ref) (`centroids=true`).
     126             : 
     127             : The additionally returned `center` is the `mean` or [`centroid`](@ref).
     128             : 
     129             : See also [`centroid`](@ref)
     130             : """
     131           4 : function pca(g::AbstractGeometry; centroids::Bool=false)
     132           2 :     x = position(g)
     133           2 :     mesh = tessellation(g)
     134             : 
     135           3 :     center = centroids ? centroid(g) : Statistics.mean(g)
     136             : 
     137          10 :     xxt_c(x) = xxt(x - center)
     138          10 :     xxt(x) = x * x'
     139             : 
     140           2 :     C =
     141             :         if centroids
     142           1 :             mean(xxt_c(x[v]) for v in vertices(mesh))
     143             :         else
     144             : 
     145           3 :             mean(xxt_c(centroid(g, f)) for f in faces(mesh))
     146             :         end
     147             : 
     148           2 :     λ, U = eigen(Symmetric(C))
     149             : 
     150           2 :     U, λ, center
     151             : end
     152             : 
     153             : """
     154             :     g = geometry(mesh, x)
     155             : 
     156             :     xmin, xmax = extrema(g)
     157             : 
     158             : Compute *axis aligned bounding box* spanned by extrema `xmin, xmax`.
     159             : 
     160             : See also [`radius`](@ref)
     161             : """
     162           1 : function Base.extrema(g::AbstractGeometry)
     163           1 :     x = position(g)
     164           1 :     extrema(x[v] for v in vertices(tessellation(g)))
     165             : end
     166             : 
     167             : """
     168             :     g = geometry(mesh, x)
     169             : 
     170             :     r = radius(mesh[; center=mean(g)])
     171             : 
     172             : Compute (maximum) radius of surface `mesh` w.r.t `center`.
     173             : 
     174             : See also [`Base.extrema`](@ref), [`Statistics.mean`](@ref)
     175             : """
     176           2 : function radius(g::AbstractGeometry; center = Statistics.mean(g))
     177           1 :     x = position(g)
     178           1 :     maximum(norm(x[v] - center) for v in vertices(tessellation(g)))
     179             : end
     180             : 
     181             : # TODO: transform, see AffineMap: apply to property
     182             : 
     183             : # TODO: bounding sphere, bounding ellipsoid
     184             : 
     185             : # TODO: define norm as norm(-(extrema(g)...)); diameter

Generated by: LCOV version 1.16