334 lines
6.1 KiB
Mathematica
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;
|