Graph3D-정점을 MoleculePlot3D로 교체

Aug 24 2020

3 차원 그래프의 정점을 개별 Graphics3D객체로 어떻게 바꿀 수 있습니까?

구체적인 경우에는 화학 네트워크를 시각화하고 정점을 각각의 MoleculePlot3D표현으로 바꾸고 싶습니다 . 티저로서 현재 작업중인 3D 그래프입니다. 최종 응용 프로그램을 상상할 수 있습니다. :)

이 게시물 의 아이디어를 사용하여 좌표를 설정했습니다.

빨간색 구는 3 차원 분자 플롯으로 대체해야합니다.

이 최소한의 예를 고려하십시오.

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에서 극단적 인 스케일링을 수행 할 필요가없는 비교적 작은 분자입니다.

답변

2 JasonB. Aug 25 2020 at 02:35

이 대답은 시스템의 표현식 내부Inset 에서 그래픽 프리미티브를 모두 피하고 가져 오기 때문에 출력을 재구성하는 향후 버전에서 중단 될 수 있기 때문에 약간 취약합니다 .MoleculePlot3DMoleculePlot3D

검사에 따르면 MoleculePlot3D에서 반환 한 Graphics3D에는 항상 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
]