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

565 lines
13 KiB
Mathematica

(* ::Package:: *)
(* ::Title:: *)
(*AggregateData*)
(* ::Subtitle:: *)
(*Data such as slice totals, slices, or dense grids, etc.*)
(* ::Text:: *)
(*Copyright Contributors to the OpenVDB Project*)
(*SPDX-License-Identifier: Apache-2.0*)
(* ::Section:: *)
(*Initialization & Usage*)
Package["OpenVDBLink`"]
PackageExport["OpenVDBActiveVoxelSliceTotals"]
PackageExport["OpenVDBSlice"]
PackageExport["OpenVDBData"]
PackageExport["OpenVDBActiveTiles"]
PackageExport["OpenVDBActiveVoxels"]
OpenVDBActiveVoxelSliceTotals::usage = "OpenVDBActiveVoxelSliceTotals[expr] computes active voxel totals for each horizontal slice of an OpenVDB grid.";
OpenVDBSlice::usage = "OpenVDBSlice[expr, z] returns a slice of an OpenVDB grid at height z.";
OpenVDBData::usage = "OpenVDBData[expr] returns a dense array representation of an OpenVDB grid.";
OpenVDBActiveTiles::usage = "OpenVDBActiveTiles[expr] returns all active tiles of an OpenVDB grid.";
OpenVDBActiveVoxels::usage = "OpenVDBActiveVoxels[expr] returns all active voxels of an OpenVDB grid as a SparseArray.";
(* ::Section:: *)
(*Totals*)
(* ::Subsection::Closed:: *)
(*OpenVDBActiveVoxelSliceTotals*)
(* ::Subsubsection::Closed:: *)
(*Main*)
OpenVDBActiveVoxelSliceTotals[args___] /; !CheckArgs[OpenVDBActiveVoxelSliceTotals[args], {1, 3}] = $Failed;
OpenVDBActiveVoxelSliceTotals[args___] :=
With[{res = iOpenVDBActiveVoxelSliceTotals[args]},
res /; res =!= $Failed
]
OpenVDBActiveVoxelSliceTotals[args___] := mOpenVDBActiveVoxelSliceTotals[args]
(* ::Subsubsection::Closed:: *)
(*iOpenVDBActiveVoxelSliceTotals*)
iOpenVDBActiveVoxelSliceTotals[vdb_?carefulNonMaskGridQ, {z1_, z2_} -> regime_?regimeQ, cntfunc_] /; z1 <= z2 :=
Block[{zindex, counter, counts},
zindex = regimeConvert[vdb, {z1, z2}, regime -> $indexregime];
counter = parseSliceTotalCounter[cntfunc];
(
counts = vdb[counter[##]]& @@ zindex;
counts /; ArrayQ[counts, _, NumericQ]
) /; StringQ[counter] && (cntfunc === "Count" || !OpenVDBBooleanGridQ[vdb])
]
iOpenVDBActiveVoxelSliceTotals[vdb_, {z1_?NumericQ, z2_?NumericQ}, args___] := iOpenVDBActiveVoxelSliceTotals[vdb, {z1, z2} -> $indexregime, args]
iOpenVDBActiveVoxelSliceTotals[vdb_?OpenVDBGridQ, Automatic, args___] := iOpenVDBActiveVoxelSliceTotals[vdb, vdb["IndexBoundingBox"][[-1]], args]
iOpenVDBActiveVoxelSliceTotals[vdb_] := iOpenVDBActiveVoxelSliceTotals[vdb, Automatic, Automatic]
iOpenVDBActiveVoxelSliceTotals[vdb_, zs_] := iOpenVDBActiveVoxelSliceTotals[vdb, zs, Automatic]
iOpenVDBActiveVoxelSliceTotals[___] = $Failed;
parseSliceTotalCounter = Replace[#, {"Value"|Automatic -> "sliceVoxelValueTotals", "Count" -> "sliceVoxelCounts", _ -> $Failed}, {0}]&;
(* ::Subsubsection::Closed:: *)
(*Argument conform & completion*)
registerForLevelSet[iOpenVDBActiveVoxelSliceTotals, 1];
SyntaxInformation[OpenVDBActiveVoxelSliceTotals] = {"ArgumentsPattern" -> {_, _., _.}};
addCodeCompletion[OpenVDBActiveVoxelSliceTotals][None, None, {"Value", "Count"}];
OpenVDBDefaultSpace[OpenVDBActiveVoxelSliceTotals] = $indexregime;
(* ::Subsubsection::Closed:: *)
(*Messages*)
mOpenVDBActiveVoxelSliceTotals[expr_, ___] /; messageGridQ[expr, OpenVDBActiveVoxelSliceTotals] = $Failed;
mOpenVDBActiveVoxelSliceTotals[expr_, ___] /; messageNonMaskGridQ[expr, OpenVDBActiveVoxelSliceTotals] = $Failed;
mOpenVDBActiveVoxelSliceTotals[_, zspec_, ___] /; messageZSpecQ[zspec, OpenVDBActiveVoxelSliceTotals] = $Failed;
mOpenVDBActiveVoxelSliceTotals[_, _, cntfunc_] :=
(
If[parseSliceTotalCounter[cntfunc] === $Failed,
Message[OpenVDBActiveVoxelSliceTotals::cntr, cntfunc, 3]
];
$Failed
);
mOpenVDBActiveVoxelSliceTotals[___] = $Failed;
OpenVDBActiveVoxelSliceTotals::cntr = "`1` at position `2` is not one of \"Value\", \"Count\", or Automatic.";
(* ::Section:: *)
(*Slice*)
(* ::Subsection::Closed:: *)
(*OpenVDBSlice*)
(* ::Subsubsection::Closed:: *)
(*Main*)
Options[OpenVDBSlice] = {"MirrorSlice" -> False};
OpenVDBSlice[args___] /; !CheckArgs[OpenVDBSlice[args], {1, 3}] = $Failed;
OpenVDBSlice[args___] :=
With[{res = iOpenVDBSlice[args]},
res /; res =!= $Failed
]
OpenVDBSlice[args___] := mOpenVDBSlice[args]
(* ::Subsubsection::Closed:: *)
(*iOpenVDBSlice*)
Options[iOpenVDBSlice] = Options[OpenVDBSlice];
iOpenVDBSlice[vdb_?carefulNonMaskGridQ, z_?NumericQ -> regime_?regimeQ, bds_?bounds2DQ, OptionsPattern[]] :=
Block[{mirrorQ, threadedQ, zindex, bdsindex, data},
mirrorQ = TrueQ[OptionValue["MirrorSlice"]];
threadedQ = True;
zindex = regimeConvert[vdb, z, regime -> $indexregime];
bdsindex = regimeConvert[vdb, bds, regime -> $indexregime];
data = vdb["gridSlice"[zindex, bdsindex, mirrorQ, threadedQ]];
data /; ArrayQ[data]
]
iOpenVDBSlice[vdb_, z_?NumericQ, args___] := iOpenVDBSlice[vdb, z -> $indexregime, args]
iOpenVDBSlice[vdb_?carefulNonMaskGridQ, z_, Automatic, opts___] := iOpenVDBSlice[vdb, z, Most[vdb["IndexBoundingBox"]], opts]
iOpenVDBSlice[vdb_, z_, opts:OptionsPattern[]] := iOpenVDBSlice[vdb, z, Automatic, opts]
iOpenVDBSlice[___] = $Failed;
(* ::Subsubsection::Closed:: *)
(*Argument conform & completion*)
registerForLevelSet[iOpenVDBSlice, 1];
SyntaxInformation[OpenVDBSlice] = {"ArgumentsPattern" -> {_, _, _., OptionsPattern[]}};
OpenVDBDefaultSpace[OpenVDBSlice] = $indexregime;
(* ::Subsubsection::Closed:: *)
(*Messages*)
mOpenVDBSlice[expr_, ___] /; messageGridQ[expr, OpenVDBSlice] = $Failed;
mOpenVDBSlice[expr_, ___] /; messageNonMaskGridQ[expr, OpenVDBSlice] = $Failed;
mOpenVDBSlice[_, z_, ___] /; messageZSliceQ[z, OpenVDBSlice] = $Failed;
mOpenVDBSlice[_, _, bbox_, ___] /; message2DBBoxQ[bbox, OpenVDBSlice] = $Failed;
mOpenVDBSlice[___] = $Failed;
(* ::Section:: *)
(*Data*)
(* ::Subsection::Closed:: *)
(*OpenVDBData*)
(* ::Subsubsection::Closed:: *)
(*Main*)
OpenVDBData[args___] /; !CheckArgs[OpenVDBData[args], {1, 2}] = $Failed;
OpenVDBData[args___] :=
With[{res = iOpenVDBData[args]},
res /; res =!= $Failed
]
OpenVDBData[args___] := mOpenVDBData[args]
(* ::Subsubsection::Closed:: *)
(*iOpenVDBData*)
iOpenVDBData[vdb_?carefulNonMaskGridQ, bds_?bounds3DQ -> regime_?regimeQ] :=
Block[{bdsindex, data},
bdsindex = regimeConvert[vdb, bds, regime -> $indexregime];
data = vdb["gridData"[bdsindex]];
data /; ArrayQ[data]
]
iOpenVDBData[vdb_?carefulNonMaskGridQ] := iOpenVDBData[vdb, vdb["IndexBoundingBox"] -> $indexregime]
iOpenVDBData[vdb_, Automatic] := iOpenVDBData[vdb, vdb["IndexBoundingBox"] -> $indexregime]
iOpenVDBData[vdb_, bspec_List] /; bounds3DQ[bspec] || intervalQ[bspec] := iOpenVDBData[vdb, bspec -> $indexregime]
iOpenVDBData[vdb_?carefulNonMaskGridQ, int_?intervalQ -> regime_?regimeQ] :=
Block[{bds2d},
bds2d = regimeConvert[vdb, Most[vdb["IndexBoundingBox"]], $indexregime -> regime];
iOpenVDBData[vdb, Append[bds2d, int] -> regime] /; bounds2DQ[bds2d]
]
iOpenVDBData[___] = $Failed;
(* ::Subsubsection::Closed:: *)
(*Argument conform & completion*)
registerForLevelSet[iOpenVDBData, 1];
SyntaxInformation[OpenVDBData] = {"ArgumentsPattern" -> {_, _.}};
OpenVDBDefaultSpace[OpenVDBData] = $indexregime;
(* ::Subsubsection::Closed:: *)
(*Messages*)
mOpenVDBData[expr_, ___] /; messageGridQ[expr, OpenVDBData] = $Failed;
mOpenVDBData[expr_, ___] /; messageNonMaskGridQ[expr, OpenVDBData] = $Failed;
mOpenVDBData[_, bbox_, ___] /; message3DBBoxQ[bbox, OpenVDBData] = $Failed;
mOpenVDBData[___] = $Failed;
(* ::Section:: *)
(*Active regions*)
(* ::Subsection::Closed:: *)
(*OpenVDBActiveTiles*)
(* ::Subsubsection::Closed:: *)
(*Main*)
Options[OpenVDBActiveTiles] = {"PartialOverlap" -> True};
OpenVDBActiveTiles[args___] /; !CheckArgs[OpenVDBActiveTiles[args], {1, 2}] = $Failed;
OpenVDBActiveTiles[args___] :=
With[{res = iOpenVDBActiveTiles[args]},
res /; res =!= $Failed
]
OpenVDBActiveTiles[args___] := mOpenVDBActiveTiles[args]
(* ::Subsubsection::Closed:: *)
(*iOpenVDBActiveTiles*)
Options[iOpenVDBActiveTiles] = Options[OpenVDBActiveTiles];
iOpenVDBActiveTiles[vdb_?OpenVDBGridQ, bds_?bounds3DQ -> regime_?regimeQ, OptionsPattern[]] :=
Block[{bdsindex, partialoverlap, tiles},
bdsindex = regimeConvert[vdb, bds, regime -> $indexregime];
partialoverlap = TrueQ[OptionValue["PartialOverlap"]];
tiles = vdb["activeTiles"[bdsindex, partialoverlap]];
tiles /; ListQ[tiles]
]
iOpenVDBActiveTiles[vdb_?OpenVDBGridQ, opts:OptionsPattern[]] := iOpenVDBActiveTiles[vdb, vdb["IndexBoundingBox"] -> $indexregime, opts]
iOpenVDBActiveTiles[vdb_?OpenVDBGridQ, Automatic, opts:OptionsPattern[]] := iOpenVDBActiveTiles[vdb, vdb["IndexBoundingBox"] -> $indexregime, opts]
iOpenVDBActiveTiles[vdb_, bds_?bounds3DQ, opts:OptionsPattern[]] := iOpenVDBActiveTiles[vdb, bds -> $indexregime, opts]
iOpenVDBActiveTiles[___] = $Failed;
(* ::Subsubsection::Closed:: *)
(*Argument conform & completion*)
registerForLevelSet[iOpenVDBActiveTiles, 1];
SyntaxInformation[OpenVDBActiveTiles] = {"ArgumentsPattern" -> {_, _., OptionsPattern[]}};
OpenVDBDefaultSpace[OpenVDBActiveTiles] = $indexregime;
(* ::Subsubsection::Closed:: *)
(*Messages*)
mOpenVDBActiveTiles[expr_, ___] /; messageGridQ[expr, OpenVDBActiveTiles] = $Failed;
mOpenVDBActiveTiles[_, bbox_, ___] /; message3DBBoxQ[bbox, OpenVDBActiveTiles] = $Failed;
mOpenVDBActiveTiles[___] = $Failed;
(* ::Subsection::Closed:: *)
(*OpenVDBActiveVoxels*)
(* ::Subsubsection::Closed:: *)
(*Main*)
OpenVDBActiveVoxels[args___] /; !CheckArgs[OpenVDBActiveVoxels[args], {1, 3}] = $Failed;
OpenVDBActiveVoxels[args___] :=
With[{res = pOpenVDBActiveVoxels[args]},
res /; res =!= $Failed
]
OpenVDBActiveVoxels[args___] := mOpenVDBActiveVoxels[args]
(* ::Subsubsection::Closed:: *)
(*pOpenVDBActiveVoxels*)
pOpenVDBActiveVoxels[vdb_?OpenVDBGridQ, bds_?bounds3DQ -> regime_?regimeQ, ret_] :=
Block[{bdsindex, res},
bdsindex = regimeConvert[vdb, bds, regime -> $indexregime];
res = iOpenVDBActiveVoxels[vdb, bdsindex, ret];
res /; res =!= $Failed
]
pOpenVDBActiveVoxels[vdb_?OpenVDBGridQ] := pOpenVDBActiveVoxels[vdb, vdb["IndexBoundingBox"] -> $indexregime]
pOpenVDBActiveVoxels[vdb_?OpenVDBGridQ, Automatic, args___] := pOpenVDBActiveVoxels[vdb, vdb["IndexBoundingBox"] -> $indexregime, args]
pOpenVDBActiveVoxels[vdb_, bds_List, args___] := pOpenVDBActiveVoxels[vdb, bds -> $indexregime, args]
pOpenVDBActiveVoxels[vdb_, bds_] := pOpenVDBActiveVoxels[vdb, bds, Automatic]
pOpenVDBActiveVoxels[___] = $Failed;
(* ::Subsubsection::Closed:: *)
(*Argument conform & completion*)
registerForLevelSet[pOpenVDBActiveVoxels, 1];
SyntaxInformation[OpenVDBActiveVoxels] = {"ArgumentsPattern" -> {_, _., _.}};
OpenVDBDefaultSpace[OpenVDBActiveVoxels] = $indexregime;
addCodeCompletion[OpenVDBActiveVoxels][None, None, {"SparseArray", "Positions", "Values"}];
(* ::Subsubsection::Closed:: *)
(*iOpenVDBActiveVoxels*)
iOpenVDBActiveVoxels[vdb_, bds_, "SparseArray"|Automatic] /; AnyTrue[{OpenVDBScalarGridQ, OpenVDBIntegerGridQ, OpenVDBBooleanGridQ}, #[vdb]&] :=
Block[{res},
res = vdb["activeVoxels"[bds]];
res /; ArrayQ[res, 3]
]
iOpenVDBActiveVoxels[vdb_?OpenVDBVectorGridQ, bds_, "SparseArray"|Automatic] :=
Block[{pos, vals, dims, offset, res},
pos = iOpenVDBActiveVoxels[vdb, bds, "Positions"];
vals = iOpenVDBActiveVoxels[vdb, bds, "Values"];
(
dims = Abs[Subtract @@@ bds] + 1;
offset = 1 - bds[[All, 1]];
Statistics`Library`MatrixRowTranslate[pos, offset];
res = SparseArray[pos -> #, dims]& /@ Transpose[vals];
res /; VectorQ[res, ArrayQ[#, 3]&]
) /; pos =!= $Failed && vals =!= $Failed
]
iOpenVDBActiveVoxels[vdb_?OpenVDBMaskGridQ, bds_, "SparseArray"|Automatic] :=
Block[{pos, dims, offset},
pos = vdb["activeVoxelPositions"[bds]];
(
dims = 1 + Abs[Subtract @@@ bds];
offset = 1 - bds[[All, 1]];
Statistics`Library`MatrixRowTranslate[pos, offset];
(
SparseArray[pos -> _, dims]
) /; Min[dims] > 0
) /; MatrixQ[pos, IntegerQ]
]
iOpenVDBActiveVoxels[vdb_, bds_, "Positions"] :=
Block[{res},
res = vdb["activeVoxelPositions"[bds]];
res /; MatrixQ[res, IntegerQ]
]
iOpenVDBActiveVoxels[vdb_?nonMaskGridQ, bds_, "Values"] :=
Block[{res},
res = vdb["activeVoxelValues"[bds]];
res /; ArrayQ[res, _, NumericQ]
]
iOpenVDBActiveVoxels[___] = $Failed;
(* ::Subsubsection::Closed:: *)
(*Messages*)
mOpenVDBActiveVoxels[expr_, ___] /; messageGridQ[expr, OpenVDBActiveVoxels] = $Failed;
mOpenVDBActiveVoxels[_, bbox_, ___] /; message3DBBoxQ[bbox, OpenVDBActiveVoxels] = $Failed;
mOpenVDBActiveVoxels[_, _, ret_, ___] /; !MatchQ[ret, "SparseArray"|"Positions"|"Values"|Automatic] :=
(
Message[OpenVDBActiveVoxels::rettype, 3];
$Failed
)
mOpenVDBActiveVoxels[_?OpenVDBMaskGridQ, _, ret_, ___] /; !MatchQ[ret, "SparseArray"|"Values"] :=
(
Message[OpenVDBActiveVoxels::mask];
$Failed
)
mOpenVDBActiveVoxels[___] = $Failed;
OpenVDBActiveVoxels::rettype = "The value at position `1` should be one of \"SparseArray\", \"Positions\", \"Values\", or Automatic.";
OpenVDBActiveVoxels::mask = "The return types \"SparseArray\", and \"Values\" are not supported for mask grids.";