I'm going to take this as a general question, referring to all atomic objects, not just DelaunayMesh
.
By design, atomic objects like DelaunayMesh
, SparseArray
, Graph
, etc. or even Association
and Rational
are not meant to be accessed directly as a Mathematica expression. There are various reasons why an object was made atomic, typically related to performance (think of the change from v8 to v9 when Image
became atomic).
These objects usually have some sort of interface to allow extracting information from them. This is what we should use, as this is the only supported (i.e. guaranteed to be robust and compatible) way. For your example, you can extract the desired information as MeshCells[r, 3]
. For a sparse array, we can extract the components of the objects with sa["NonzeroPositions"]
, sa["NonzeroValues"]
, etc. For a Graph
object, we can use VertexList
and EdgeList
.
Usually, the standard interface works well. But unfortunately, occasionally it happens that a use case was not anticipated by Wolfram. This happened recently to me when I had a need to extract an edge list of the graph in terms of indices, with good performance. I know the information is there, and I know that it can be extracted quickly, as e.g. AdjacencyMatrix
seems to do it, but there's no documented way for me to get access to the raw information. These really made me want to poke around the internal structure of Graph
... but doing such things would be a very bad idea if we need any sort of robustness, especially inside a production package.
However, to do it at all, we need to get access it the expression's "full form". You noticed that virtually all atomic expressions have a full form, even though it is mostly inaccessible. Why is this so, if they are atomic? I believe that the answer is that often there is a need to serialize Mathematica expressions, either to write them into an .m
file, save them in a notebook (when possible), or to send them through a MathLink connection. This is done by first representing them as a compound expression, which might not map directly to the internal structure of the atomic object, but should represent it fully.
How well this "full form" integrates into the rest of the language varies from case to case. E.g. SparseArray
and Rational
can be accessed using pattern matching:
sa = SparseArray[{5, 7} -> 1];
Replace[sa, HoldPattern@SparseArray[guts___] :> {guts}]
(* {Automatic, {5, 7}, 0, {1, {{0, 0, 0, 0, 0, 1}, {{7}}}, {1}}} *)
Graph
cannot:
g = RandomGraph[{5,10}];
MatchQ[g, HoldPattern@Graph[___]]
We know though that it does have a full form ...
In[]:= InputForm[g]
Out[]//InputForm=
Graph[{1, 2, 3, 4, 5}, {Null, SparseArray[Automatic, {5, 5}, 0,
{1, {{0, 4, 8, 12, 16, 20}, {{2}, {3}, {4}, {5}, {1}, {3}, {4}, {5}, {1}, {2}, {4},
{5}, {1}, {2}, {3}, {5}, {1}, {2}, {3}, {4}}}, Pattern}]}]
I think that the only way to get to it is to first convert the atomic object to another representation. We could convert it to a string and back, e.g.
ToExpression[ToString[g, InputForm], InputForm, Hold]
Hold[Graph[{1, 2, 3, 4, 5}, {Null,
SparseArray[Automatic, {5, 5},
0, {1, {{0, 4, 8, 12, 16,
20}, {{2}, {3}, {4}, {5}, {1}, {3}, {4}, {5}, {1}, {2}, {4}, \
{5}, {1}, {2}, {3}, {5}, {1}, {2}, {3}, {4}}}, Pattern}]}]]
What's inside the Hold
is not an atom, it's just a compound expression with head Graph
that will immediately evaluate to an atomic graph once we remove the Hold
.
We could also use Compress
:
Uncompress[Compress[g], Hold]
Or possibly export to WDX and import back (haven't tested).
If we wanted better performance, we might send the expression through a MathLink connection and wrap it in Hold
in C code ...
These are good techniques for doing some spelunking on atoms. But doing this should really really be avoided in favour of using the standard, type-specific way of extracting information. Remember that this full form used for serialization is not meant to be used directly, it's only for serialization. It may change between versions, and it may not work the way you thought it did. Graph
for example can have several different internal representations.
Part
. What exactly are you looking to extract? Is there no existing function to extract the particular object you are trying to get?MeshCells[r, 3]
will return the tetrahedra. $\endgroup$Tetrahedron
and in general it will be helpful to be able to extract some info with the order generated in such functions. I know thatPart
does not work and I thought there could be another way to get what you want from such functions. $\endgroup$Tetrahedron
it contains numbers indicate the order of the points in the list. In another word Tetrahedron[{8, 1, 6, 4}] is equivalent toTetrahedron[points[[#]] & /@ {8, 1, 6, 4}]
$\endgroup$MeshCells[r, 3]
returns exactly that. $\endgroup$