feat: compute sha1 checksum of extended grids

This commit is contained in:
2025-03-06 07:28:32 +01:00
parent 817c02b5a6
commit bf7ae5889b
2 changed files with 109 additions and 78 deletions

View File

@@ -6,6 +6,7 @@ open FSharpPlus.Control
open ProjNet.CoordinateSystems
open Serilog
open ProjNet.FSharp
open MessagePack
open MBrace.FsPickler
//open FsKDTree
open KdTree // C# version
@@ -40,14 +41,14 @@ type Grid =
BBox: BBox
}
interface IGrid with
member x.getVertex n = x.Nodes[n]
member x.getCell n = x.Elem[n]
member x.getCellVertices n =
let a, b, c = x.Elem[n]
x.Nodes[a], x.Nodes[b], x.Nodes[c]
member x.getVertices() = x.Nodes
member x.getCells() = x.Elem
member x.getBoundingBox() = x.BBox
member this.getVertex n = this.Nodes[n]
member this.getCell n = this.Elem[n]
member this.getCellVertices n =
let a, b, c = this.Elem[n]
this.Nodes[a], this.Nodes[b], this.Nodes[c]
member this.getVertices() = this.Nodes
member this.getCells() = this.Elem
member this.getBoundingBox() = this.BBox
static member empty =
{
Elem = Array.empty
@@ -506,11 +507,25 @@ module Util =
type private IdxTree = KdTree<float, int>
type private NodeIdxTree = KdTree<float, int>
[<MessagePackObject>]
type BinGrid = {
[<Key(0)>] hash : byte[]
[<Key(1)>] vertices : (float * float)[]
[<Key(2)>] cells : (int * int * int)[]
} with
member this.toGrid (): Grid =
{
Nodes = this.vertices
Elem = this.cells
BBox = calcBBox this.vertices
}
type ExtendedGrid(grid: IGrid) =
let mutable nodeTree: NodeIdxTree option = None
let mutable elementTree: IdxTree option = None
let mutable neighborIndex: NeighborIndex option = None
let mutable centroids: Vertex [] option = None
let mutable gridHash: byte[] = [||]
let getNeighborIdx () =
match neighborIndex with
@@ -520,35 +535,35 @@ type ExtendedGrid(grid: IGrid) =
neighborIndex.Value
interface IGrid with
member x.getVertex n = grid.getVertex n
member x.getCell n = grid.getCell n
member x.getCellVertices n = grid.getCellVertices n
member x.getVertices() = grid.getVertices ()
member x.getCells() = grid.getCells ()
member x.getBoundingBox() = grid.getBoundingBox ()
member this.getVertex n = grid.getVertex n
member this.getCell n = grid.getCell n
member this.getCellVertices n = grid.getCellVertices n
member this.getVertices() = grid.getVertices ()
member this.getCells() = grid.getCells ()
member this.getBoundingBox() = grid.getBoundingBox ()
member x.NeighborIndex = neighborIndex
member x.NodeTree = nodeTree
member x.ElementTree = elementTree
member this.NeighborIndex = neighborIndex
member this.NodeTree = nodeTree
member this.ElementTree = elementTree
member x.Grid = grid
member this.Grid = grid
member x.initNeighborIndex(?cache: string) =
member this.initNeighborIndex(?cache: string) =
match neighborIndex with
| Some _ -> ()
| None -> neighborIndex <- makeNeighborIndex grid |> Some
member x.initNodeTree() =
member this.initNodeTree() =
match nodeTree with
| Some _ -> ()
| None -> nodeTree <- Util.buildNearestNodeTree grid |> Some
member x.initElementTree() =
member this.initElementTree() =
match elementTree with
| Some _ -> ()
| None -> elementTree <- Util.buildNearestElementTree grid |> Some
member x.nearestNode(p0: float, p1: float) =
member this.nearestNode(p0: float, p1: float) =
let nearest (tree: KdTree<_, _>) =
tree.GetNearestNeighbours([| p0; p1 |], 1)
|> Array.tryHead
@@ -556,49 +571,64 @@ type ExtendedGrid(grid: IGrid) =
match nodeTree with
| Some tree -> nearest tree
| None ->
x.initNodeTree ()
this.initNodeTree ()
nearest nodeTree.Value
member x.tryGetNode(p: float * float) =
x.nearestNode p
member this.tryGetNode(p: float * float) =
this.nearestNode p
|> Option.bind (fun n ->
x.getElemsSurroundingNode n
this.getElemsSurroundingNode n
|> Array.fold (fun (a: int option) e ->
if a.IsNone then
let vx = x.Grid.getCellVertices e
let vx = this.Grid.getCellVertices e
if Util.isInsideTriangle vx p then Some n else None
else a) None
)
member private x.tryFindElementTwice (grid: IGrid) (tree: IdxTree) ((p0, p1): float * float as p) =
member private this.tryFindElementTwice (grid: IGrid) (tree: IdxTree) ((p0, p1): float * float as p) =
Util.tryFindElement grid tree p
|> Option.orElse (
tree.GetNearestNeighbours([| p0; p1 |], 1)
|> Array.tryHead
|> Option.bind (fun leaf ->
x.getElemsSurroundingElem leaf.Value
this.getElemsSurroundingElem leaf.Value
|> Array.tryFind (fun eIdx ->
let vx = x.Grid.getCellVertices eIdx
let vx = this.Grid.getCellVertices eIdx
Util.isInsideTriangle vx p))
)
member x.tryGetElement p =
member this.tryGetElement p =
elementTree
|> Option.bind (fun tree ->
x.tryFindElementTwice grid tree p)
this.tryFindElementTwice grid tree p)
|> Option.orElseWith (fun () ->
x.initElementTree ()
x.tryFindElementTwice grid elementTree.Value p)
this.initElementTree ()
this.tryFindElementTwice grid elementTree.Value p)
member x.tryGetElementSloppy(p0, p1 as p) =
member this.tryGetElementSloppy(p0, p1 as p) =
match elementTree with
| Some tree -> Util.tryFindElement grid tree p
| None ->
x.initElementTree ()
// x.initNodeTree ()
this.initElementTree ()
// this.initNodeTree ()
Util.tryFindElement grid elementTree.Value p
member x.getCentroids() =
member this.getSha1() =
if gridHash.Length = 0 then
let bg : BinGrid = {
hash = [||]
vertices = (this :> IGrid).getVertices ()
cells = (this :> IGrid).getCells ()
}
let bytes = MessagePackSerializer.Serialize(bg)
let sha1 = System.Security.Cryptography.SHA1.Create()
gridHash <- sha1.ComputeHash bytes
gridHash
member this.getSha1String() =
this.getSha1() |> Convert.ToHexStringLower
member this.getCentroids() =
match centroids with
| Some cx -> cx
| None ->
@@ -606,35 +636,35 @@ type ExtendedGrid(grid: IGrid) =
centroids <- Some cx
cx
member x.calcCircumCircle e =
member this.calcCircumCircle e =
let triangle = grid.getCellVertices e
Util.Element.calcCircumscribedCircle triangle
member x.getElemsSurroundingNode n =
member this.getElemsSurroundingNode n =
getNeighborIdx ()
|> fun idx -> idx.ElemsAroundNode[n]
member x.getNodesSurroundingNode n =
member this.getNodesSurroundingNode n =
getNeighborIdx ()
|> fun idx -> idx.NodesAroundNode[n]
member x.getNodesSurroundingElem e =
member this.getNodesSurroundingElem e =
let idx = getNeighborIdx ()
let elem = grid.getCell e
getSurrounding idx.NodesAroundNode elem
member x.getElemsSurroundingElem e =
member this.getElemsSurroundingElem e =
let idx = getNeighborIdx ()
let elem = grid.getCell e
getSurrounding idx.ElemsAroundNode elem
member x.saveNeighborIndex(fname: string) =
member this.saveNeighborIndex(fname: string) =
let binarySerializer = FsPickler.CreateBinarySerializer()
let nix = getNeighborIdx ()
let pickle = binarySerializer.Pickle nix
IO.File.WriteAllBytes(fname, pickle)
member x.loadNeighborIndex(fname: string) =
member this.loadNeighborIndex(fname: string) =
let binarySerializer = FsPickler.CreateBinarySerializer()
if IO.File.Exists fname then
let pickle = IO.File.ReadAllBytes fname
@@ -645,18 +675,18 @@ type ExtendedGrid(grid: IGrid) =
else
false
member x.saveNodeTree(fname: string) =
member this.saveNodeTree(fname: string) =
let binarySerializer = FsPickler.CreateBinarySerializer()
let tree =
nodeTree
|> Option.defaultWith (fun () ->
x.initNodeTree ()
this.initNodeTree ()
nodeTree.Value)
let pickle = binarySerializer.Pickle tree
IO.File.WriteAllBytes(fname, pickle)
member x.loadNodeTree(fname: string) =
member this.loadNodeTree(fname: string) =
let binarySerializer = FsPickler.CreateBinarySerializer()
if IO.File.Exists fname then
let pickle = IO.File.ReadAllBytes fname
@@ -665,18 +695,18 @@ type ExtendedGrid(grid: IGrid) =
else
false
member x.saveElementTree(fname: string) =
member this.saveElementTree(fname: string) =
let binarySerializer = FsPickler.CreateBinarySerializer()
let tree =
elementTree
|> Option.defaultWith (fun () ->
x.initElementTree ()
this.initElementTree ()
elementTree.Value)
let pickle = binarySerializer.Pickle tree
IO.File.WriteAllBytes(fname, pickle)
member x.loadElementTree(fname: string) =
member this.loadElementTree(fname: string) =
let binarySerializer = FsPickler.CreateBinarySerializer()
if IO.File.Exists fname then
let pickle = IO.File.ReadAllBytes fname

View File

@@ -5,37 +5,38 @@
<TargetFramework>net9.0</TargetFramework>
<IsPackable>true</IsPackable>
<PackageId>Oceanbox.FvcomKit</PackageId>
<Authors/>
<Company/>
<Authors />
<Company />
<Version>5.7.0</Version>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="Types.fs"/>
<Compile Include="Grid.fs"/>
<Compile Include="Arome.fs"/>
<Compile Include="Fvcom.fs"/>
<Compile Include="Thredds.fs"/>
<Compile Include="Polygon.fs"/>
<Compile Include="Adjoin.fs"/>
<Compile Include="Interpol.fs"/>
<Compile Include="ROMS.fs"/>
<Compile Include="NorKyst.fs"/>
<Compile Include="NorShelf.fs"/>
<Compile Include="Smoothing.fs"/>
<Compile Include="Types.fs" />
<Compile Include="Grid.fs" />
<Compile Include="Arome.fs" />
<Compile Include="Fvcom.fs" />
<Compile Include="Thredds.fs" />
<Compile Include="Polygon.fs" />
<Compile Include="Adjoin.fs" />
<Compile Include="Interpol.fs" />
<Compile Include="ROMS.fs" />
<Compile Include="NorKyst.fs" />
<Compile Include="NorShelf.fs" />
<Compile Include="Smoothing.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="FSharp.Core" Version="9.0.100"/>
<PackageReference Include="FSharp.Data" Version="6.4.0"/>
<PackageReference Include="FSharpPlus" Version="1.6.1"/>
<PackageReference Include="FsPickler" Version="5.3.2"/>
<PackageReference Include="KDTree" Version="1.4.1"/>
<PackageReference Include="MathNet.Numerics.FSharp" Version="5.0.0"/>
<PackageReference Include="ProjNet.FSharp" Version="5.2.0"/>
<PackageReference Include="SDSlite.Oceanbox" Version="2.7.3"/>
<PackageReference Include="Serilog" Version="4.1.0"/>
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0"/>
<PackageReference Include="Serilog.Sinks.Seq" Version="8.0.0"/>
<PackageReference Include="Thoth.Json.Net" Version="12.0.0"/>
<PackageReference Include="FSharp.Data" Version="6.4.1" />
<PackageReference Include="FSharpPlus" Version="1.7.0" />
<PackageReference Include="FsPickler" Version="5.3.2" />
<PackageReference Include="KDTree" Version="1.4.1" />
<PackageReference Include="MathNet.Numerics.FSharp" Version="5.0.0" />
<PackageReference Include="MessagePack" Version="3.1.3" />
<PackageReference Include="ProjNet.FSharp" Version="5.2.0" />
<PackageReference Include="SDSlite.Oceanbox" Version="2.7.3" />
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
<PackageReference Include="Thoth.Json.Net" Version="12.0.0" />
<PackageReference Update="FSharp.Core" Version="9.0.200" />
</ItemGroup>
</Project>
</Project>