Graph3D - заменить вершины на MoleculePlot3D
Как мы можем заменить вершины трехмерного графа отдельными Graphics3Dобъектами?
В моем конкретном случае я хочу визуализировать химическую сеть и заменить вершины их соответствующими MoleculePlot3Dпредставлениями. В качестве тизера, это текущий 3D-график, с которым я работаю. Вы, наверное, можете себе представить финальное приложение :)
Я использовал идеи из этого поста, чтобы установить координаты.
Красные сферы следует заменить трехмерными диаграммами молекул.
Рассмотрим этот минимальный пример:
Graph3D[{"CO" \[DirectedEdge] "C", "CO" \[DirectedEdge] "O"}]
Настройка соответствующих MoleculePlot3Dэкземпляров:
vert = AssociationThread[
{"CO", "C", "O"} -> {
MoleculePlot3D[Molecule[{Atom["[C]"], Atom["[O]"]}, {Bond[{1, 2}, "Double"]}]],
MoleculePlot3D[Molecule[{Atom["[C]"]}]],
MoleculePlot3D[Molecule[{Atom["[O]"]}]]}]
Однако у меня возникли трудности с программной заменой вершин в Graph3Dфайле. Мне удалось изменить 2D-график:
Graph[{
Annotation["CO", VertexShapeFunction -> (Inset[vert["CO"], #1, Center, 2*#3] &), VertexSize -> 0.2],
Annotation["C", VertexShapeFunction -> (Inset[vert["C"], #1, Center, 2*#3] &), VertexSize -> 0.2],
Annotation["O", VertexShapeFunction -> (Inset[vert["O"], #1, Center, 2*#3] &), VertexSize -> 0.2]},
{"CO" \[DirectedEdge] "C", "CO" \[DirectedEdge] "O"}]
Как я могу это сделать в Graph3D? В полном случае я буду работать со следующими молекулами:
{"C", "C+", "CH", "CH+", "CN", "CO", "CS", "CS+", "H", "H2", "HCO+",
"HCS+", "He", "N", "O", "OH", "S", "SO", "CH2+", "CO+", "O+", "OCS+",
"S+", "SO+", "CH2", "CN+", "H2O", "HCN", "HS", "H3O+", "HS+", "CH3+",
"HNC", "H3CO+", "CH4", "N+", "N2", "H+", "OH+", "OCS", "H2O+", "H2+",
"H2S+", "H3+", "He+", "O2", "SO2"}
Таким образом, относительно небольшие молекулы без необходимости выполнять экстремальное масштабирование в MoleculePlots.
Ответы
Этот ответ Insetполностью избегает и захватывает графические примитивы изнутри выражения из системы MoleculePlot3D, и поэтому немного хрупок, потому что он может сломаться в будущей версии, которая реструктурирует вывод из MoleculePlot3D.
Проверка показывает, что Graphics3D, возвращаемый MoleculePlot3D, всегда содержит a GraphicsComplexсо всеми атомами и связями. Итак, мы можем использовать это GraphicsComplexи обернуть, GeometricTransformationчтобы функция формы вершины
molVertex[mol_][coords_, vertex_, scale_] := Module[
{graphic = MoleculePlot3D @ mol, gc},
gc = Cases[graphic, _GraphicsComplex, Infinity];
GeometricTransformation[
gc,
TranslationTransform[coords] @* ScalingTransform[scale]
]
]
Вот пример,
SeedRandom @ 42;
g = RandomGraph @ {5, 8};
mols = Map[
Molecule,
{"CCCC(C)(C)OCC", "SC1CCCC1", "O=P(O)(O)CCO", "CCCC", "F[Ti](Cl)(Cl)Cl"}
];
Graph3D[
Annotation[#,
VertexShapeFunction -> molVertex[mols[[#]]],
VertexSize -> 0.2
]& /@ VertexList[g],
EdgeList @ g
]