565 lines
13 KiB
Mathematica
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.";
|