Files
UnrealEngine/Engine/Source/ThirdParty/OpenVDB/openvdb-12.0.0/openvdb_wolfram/OpenVDBLink/Measure.m
2025-05-18 13:04:45 +08:00

334 lines
6.1 KiB
Mathematica

(* ::Package:: *)
(* ::Title:: *)
(*Measure*)
(* ::Subtitle:: *)
(*Compute area, volume, genus, Euler characteristic, ...*)
(* ::Text:: *)
(*Copyright Contributors to the OpenVDB Project*)
(*SPDX-License-Identifier: Apache-2.0*)
(* ::Section:: *)
(*Initialization & Usage*)
Package["OpenVDBLink`"]
PackageExport["OpenVDBArea"]
PackageExport["OpenVDBEulerCharacteristic"]
PackageExport["OpenVDBGenus"]
PackageExport["OpenVDBVolume"]
OpenVDBArea::usage = "OpenVDBArea[expr] finds the surface area of an OpenVDB level set.";
OpenVDBEulerCharacteristic::usage = "OpenVDBEulerCharacteristic[expr] finds the Euler characteristic of an OpenVDB level set.";
OpenVDBGenus::usage = "OpenVDBGenus[expr] finds the genus of an OpenVDB level set.";
OpenVDBVolume::usage = "OpenVDBVolume[expr] finds the volume of an OpenVDB level set.";
(* ::Section:: *)
(*OpenVDBArea*)
(* ::Subsection::Closed:: *)
(*Main*)
OpenVDBArea[args___] /; !CheckArgs[OpenVDBArea[args], {1, 2}] = $Failed;
OpenVDBArea[args___] :=
With[{res = iOpenVDBArea[args]},
res /; res =!= $Failed
]
OpenVDBArea[args___] := mOpenVDBArea[args]
(* ::Subsection::Closed:: *)
(*iOpenVDBArea*)
iOpenVDBArea[vdb_?OpenVDBScalarGridQ, regime_?regimeQ] :=
Block[{area, scale},
area = scalarArea[vdb];
(
area = regimeConvert[vdb, area, $worldregime -> regime, 2];
area
) /; area =!= $Failed
]
iOpenVDBArea[vdb_] := iOpenVDBArea[vdb, $worldregime]
iOpenVDBArea[___] = $Failed;
(* ::Subsection::Closed:: *)
(*Argument conform & completion*)
registerForLevelSet[iOpenVDBArea, 1];
SyntaxInformation[OpenVDBArea] = {"ArgumentsPattern" -> {_, _.}};
OpenVDBDefaultSpace[OpenVDBArea] = $worldregime;
(* ::Subsection::Closed:: *)
(*Utilities*)
scalarArea[vdb_?emptyVDBQ] = 0.
scalarArea[vdb_?levelSetQ] :=
With[{vol = vdb["levelSetGridArea"[]]},
vol /; NumericQ[vol]
]
scalarArea[vdb_] /; !levelSetQ[vdb] = Indeterminate;
scalarArea[___] = $Failed;
(* ::Subsection::Closed:: *)
(*Messages*)
mOpenVDBArea[expr_, ___] /; messageScalarGridQ[expr, OpenVDBArea] = $Failed;
mOpenVDBArea[_, regime_] /; messageRegimeSpecQ[regime, OpenVDBArea] = $Failed;
mOpenVDBArea[___] = $Failed;
(* ::Section:: *)
(*OpenVDBEulerCharacteristic*)
(* ::Subsection::Closed:: *)
(*Main*)
OpenVDBEulerCharacteristic[args___] /; !CheckArgs[OpenVDBEulerCharacteristic[args], 1] = $Failed;
OpenVDBEulerCharacteristic[args___] :=
With[{res = iOpenVDBEulerCharacteristic[args]},
res /; res =!= $Failed
]
OpenVDBEulerCharacteristic[args___] := mOpenVDBEulerCharacteristic[args]
(* ::Subsection::Closed:: *)
(*iOpenVDBEulerCharacteristic*)
iOpenVDBEulerCharacteristic[vdb_?OpenVDBScalarGridQ] :=
Block[{char},
char = Which[
!levelSetQ[vdb], Indeterminate,
emptyVDBQ[vdb], Undefined,
True, Replace[vdb["levelSetGridEulerCharacteristic"[]], Except[_Integer] -> $Failed, {0}]
];
char /; char =!= $Failed
]
iOpenVDBEulerCharacteristic[___] = $Failed;
(* ::Subsection::Closed:: *)
(*Argument conform & completion*)
registerForLevelSet[iOpenVDBEulerCharacteristic, 1];
SyntaxInformation[OpenVDBEulerCharacteristic] = {"ArgumentsPattern" -> {_}};
(* ::Subsection::Closed:: *)
(*Messages*)
mOpenVDBEulerCharacteristic[expr_] /; messageScalarGridQ[expr, OpenVDBEulerCharacteristic] = $Failed;
mOpenVDBEulerCharacteristic[___] = $Failed;
(* ::Section:: *)
(*OpenVDBGenus*)
(* ::Subsection::Closed:: *)
(*Main*)
OpenVDBGenus[args___] /; !CheckArgs[OpenVDBGenus[args], 1] = $Failed;
OpenVDBGenus[args___] :=
With[{res = iOpenVDBGenus[args]},
res /; res =!= $Failed
]
OpenVDBGenus[args___] := mOpenVDBGenus[args]
(* ::Subsection::Closed:: *)
(*iOpenVDBGenus*)
iOpenVDBGenus[vdb_?OpenVDBScalarGridQ] :=
Block[{genus},
genus = Which[
!levelSetQ[vdb], Indeterminate,
emptyVDBQ[vdb], Undefined,
True, Replace[vdb["levelSetGridGenus"[]], Except[_Integer] -> $Failed, {0}]
];
genus /; genus =!= $Failed
]
iOpenVDBGenus[___] = $Failed;
(* ::Subsection::Closed:: *)
(*Argument conform & completion*)
registerForLevelSet[iOpenVDBGenus, 1];
SyntaxInformation[OpenVDBGenus] = {"ArgumentsPattern" -> {_}};
(* ::Subsection::Closed:: *)
(*Messages*)
mOpenVDBGenus[expr_, ___] /; messageScalarGridQ[expr, OpenVDBGenus] = $Failed;
mOpenVDBGenus[___] = $Failed;
(* ::Section:: *)
(*OpenVDBVolume*)
(* ::Subsection::Closed:: *)
(*Main*)
OpenVDBVolume[args___] /; !CheckArgs[OpenVDBVolume[args], {1, 2}] = $Failed;
OpenVDBVolume[args___] :=
With[{res = iOpenVDBVolume[args]},
res /; res =!= $Failed
]
OpenVDBVolume[args___] := mOpenVDBVolume[args]
(* ::Subsection::Closed:: *)
(*iOpenVDBVolume*)
iOpenVDBVolume[vdb_?OpenVDBScalarGridQ, regime_?regimeQ] :=
Block[{volume, scale},
volume = scalarVolume[vdb];
(
volume = regimeConvert[vdb, volume, $worldregime -> regime, 3];
volume
) /; volume =!= $Failed
]
iOpenVDBVolume[vdb_] := iOpenVDBVolume[vdb, $worldregime]
iOpenVDBVolume[___] = $Failed;
(* ::Subsection::Closed:: *)
(*Argument conform & completion*)
registerForLevelSet[iOpenVDBVolume, 1];
SyntaxInformation[OpenVDBVolume] = {"ArgumentsPattern" -> {_, _.}};
OpenVDBDefaultSpace[OpenVDBVolume] = $worldregime;
(* ::Subsection::Closed:: *)
(*Utilities*)
scalarVolume[vdb_?emptyVDBQ] := If[TrueQ[Negative[vdb["getBackgroundValue"[]]]], \[Infinity], 0.]
scalarVolume[vdb_?levelSetQ] :=
With[{vol = vdb["levelSetGridVolume"[]]},
vol /; NumericQ[vol]
]
scalarVolume[vdb_?fogVolumeQ] :=
With[{tots = OpenVDBActiveVoxelSliceTotals[vdb]},
(
Total[tots] * vdb["VoxelSize"]^3
) /; VectorQ[tots, NumericQ]
]
scalarVolume[vdb_] /; !levelSetQ[vdb] && !fogVolumeQ[vdb] = Indeterminate;
scalarVolume[___] = $Failed;
(* ::Subsection::Closed:: *)
(*Messages*)
mOpenVDBVolume[expr_, ___] /; messageScalarGridQ[expr, OpenVDBVolume] = $Failed;
mOpenVDBVolume[_, regime_] /; messageRegimeSpecQ[regime, OpenVDBVolume] = $Failed;
mOpenVDBVolume[___] = $Failed;