빛나는 가중치 그래프 (네트워크) : 정점 및 가장자리

Aug 19 2020

다음을 수행하는 방법 (바람직하게 간단하고 큰 그래프에 최적화 된 성능 / 속도)을 찾으려고합니다.

  • 글로우 효과 및 강도에 따라 그래프 정점 스타일링 VertexWeight

  • 글로우 효과 및 강도에 따라 그래프 가장자리 스타일 지정 EdgeWeight

  • DirectedEdge글로우 효과 스타일링도 바람직합니다 (단순함을 위해에서 시작할 수 있음 UndirectedEdge)

예를 들면 다음과 같습니다.

RandomGraph[{20,100},
VertexWeight->RandomReal[1,20],
EdgeWeight->RandomReal[1,100],
Background->Black,
BaseStyle->White]

나는 가장자리도 빛날 필요가 있다는 점을 제외하고는 아래와 비슷한 비주얼을 찾고 있습니다.

내가 겪고있는 문제.

1. 놀라운 빛의 간단한 구현

나는 다양한 글로우 (를 포함하여 효과를 본 적이 본 빛나는 점에 대해)하지만에게 최고의 대 비주얼 성능 아이디어에 대한 전문가를. 놀랍게도 나는 주위에 빛나는 선에 대해 많이 보지 못했습니다. 나는 순진하게 다음과 같은 것으로 시작 하겠지만 아마도 시각적으로나 성능면에서 향상 될 수 있습니다.

bsc=BSplineCurve[{{0,0},{1,1},{2,0}}];
Graphics[
    Table[{White,Opacity[1/k^1.2],Thickness[.005k],CapForm["Round"],bsc},{k,20}],
Background->Black]

2. 빛을 내기 위해 가중치 전달

VertexShapeFunction및을 알고 있지만 EdgeShapeFunction가중치를 최적으로 전달하는 방법과 이러한 속성이 올바른 접근 방식인지 잘 모르겠습니다.

내장 기능에서 빛남

이 기능이 약간의 빛을내는 것을 발견했습니다.

ComplexPlot[z^2+1,{z,-2-2I,2+2I},ColorFunction->"CyclicReImLogAbs"]

그리고 @EC가 아래의 답변에서 알 수 있듯이

ImageAdjust[DistanceTransform[Graphics[Point[RandomReal[1,{100,2}]]]]]

감사합니다. 도움을 주셔서 감사합니다!

답변

14 flinty Aug 19 2020 at 22:41

ImageAdd이미지 마스크를 흐리게 복사 하여 전체적인 글로우 효과를 얻을 수 있습니다 . 확실히 그것은 약간 기본적이지만 그 효과는 매력적입니다. 내가 사용하여 '뇌'네트워크를 만들기 위해 선택 AnatomyDataNearestNeighbourGraph는 약간의 과대 AI 마케팅 것처럼 보이게 :

SeedRandom[123];
brain = AnatomyData[Entity["AnatomicalStructure", "Brain"], "MeshRegion"];
boundary = RegionBoundary[brain];
nng = NearestNeighborGraph[RandomPoint[boundary, 1000], 7];
brainnetimg = Rasterize[
   GraphPlot3D[nng, ViewPoint -> Left, 
    VertexStyle -> Directive[AbsolutePointSize[7], White], 
    EdgeStyle -> Directive[AbsoluteThickness[2], White], 
    Background -> Black]
   , ImageSize -> 1000];
ImageAdd[ImageAdjust[Blur[Binarize@brainnetimg, 7], .1], 
 ImageMultiply[brainnetimg, 
  LinearGradientImage[{Blue, Cyan, Purple}, 
   ImageDimensions[brainnetimg]]]]

글로우의 크기에 영향을 미치는 가중치를 얻으려면 아마도 EdgeShapeFunctionVertexShapeFunction. 알파가있는 렌즈 효과의 빌보드 텍스처를 만들고이 이미지를 정점에 사용했습니다.

또한 선을 쌓는 질문에서 언급 한 가장자리 글로우 효과를 사용했습니다. 더 많은 가중치를 가진 가장자리는 더 많은 글로우를 가져야하며 더 많은 가중치를 가진 정점은 더 큰 플레어를 갖게됩니다.

SeedRandom[123];
G = SpatialGraphDistribution[100, 0.20];
g = RandomGraph[G];
glowtexture = Import["lensbb.png"];
edgeWeights = RandomReal[1, EdgeCount[g]];
vertexWeights = RandomReal[1, VertexCount[g]];

edgeShapeFunc = 
  With[{weight = AnnotationValue[{g, #2}, EdgeWeight]}, 
    Table[{RGBColor[0.7, 1.0, 0.9], Opacity[1/k^1.3], 
      Thickness[.001 k*weight], CapForm["Round"], Line[#1]}, {k, 20}]] &;

vertexShapeFunc = 
  With[{weight = AnnotationValue[{g, #2}, VertexWeight]}, 
    Inset[glowtexture, #1, Center, weight*0.3]] &;

g = Graph[g, EdgeWeight -> edgeWeights, VertexWeight -> vertexWeights,
   VertexShapeFunction -> vertexShapeFunc, Background -> Black, 
  EdgeShapeFunction -> edgeShapeFunc, PlotRangePadding -> .1]

위의 라인 스택 / 불투명도 트릭을 사용하여 빛나는 가장자리를 생성하는 대신 텍스처 다각형을 대신 사용할 수도 있습니다. 이것은 더 빠르지 만 단점은 가장자리가 너무 두꺼워지면 캡이 보이고보기 흉한 것입니다.

g = Graph[UndirectedEdge @@@ {{1, 2}, {2, 3}, {3, 1}}];
edgeWeights = {1, 2, 3}/6.;
vertexWeights = {1, 2, 3}/6.;

glowtexture = Import["lensbb.png"];
edgegradimg = LinearGradientImage[{Transparent,Cyan,Transparent}, {64,64}];

edgeShapeFunc = 
  Module[{weight = AnnotationValue[{g, #2}, EdgeWeight], s = 1/10., 
     vec = #1[[2]] - #1[[1]], perp},
    perp = Cross[vec];
    {Texture[edgegradimg], 
     Polygon[{
         #1[[1]]-perp*weight*s, 
         #1[[1]]+perp*weight*s,
         #1[[2]]+perp*weight*s,
         #1[[2]]-perp*weight*s
     }, VertexTextureCoordinates -> {{0,0},{1,0},{1,1},{0,1}}]
    }] &;

vertexShapeFunc = 
  With[{weight = AnnotationValue[{g, #2}, VertexWeight]}, 
    Inset[glowtexture, #1, Center, weight*3]] &;

g = Graph[g, EdgeWeight -> edgeWeights, VertexWeight -> vertexWeights,
   VertexShapeFunction -> vertexShapeFunc, Background -> Black, 
  EdgeShapeFunction -> edgeShapeFunc, PlotRangePadding -> .5]

8 C.E. Aug 19 2020 at 14:37

DistanceTransform 글로우에 필요한 유형의 거리 맵을 제공합니다.

먼저 광원을 정의합니다.

bg = ConstantImage[White, 200];
line = HighlightImage[
  bg, {
   Black,
   Thick,
   Line[{{50, 100}, {150, 100}}]
   }]

다음으로 거리 변환을 계산합니다. 결과 이미지의 1이 이미지의 대각선에 해당하도록 크기를 조정합니다.

glow = ColorNegate@Image[Divide[
     ImageData@DistanceTransform[line],
     200 Sqrt[2]
     ]^0.2]

0.2는 글로우가 꺼지는 속도를 제어합니다.

다음으로 글로우에 색상을 적용 할 수 있습니다.

glow ConstantImage[Red, 200]

또한 색상 기능을 적용 할 수도 있습니다.

ImageApply[List @@ ColorData["AvocadoColors", #] &, glow]

멋진 색상 기능을 만드는 것은 예제에서와 같은 멋진 빛을 만드는 데 중요합니다.

이 기술을 사용하여 빛나는 그래프를 만드는 것은 매우 간단합니다. 모든 모서리는 선이고 모든 정점은 점 또는 디스크입니다. 결국 하나의 이미지로 통합 할 수 있습니다.

이를위한 강력한 기능을 만들기 위해 독자에게 맡기겠습니다. 작은 예를 들어 보겠습니다.

예를 들어 Pappus 그래프를 사용합니다.

embedding = First@GraphData["PappusGraph", "Embeddings"];
coords = List @@@ GraphData["PappusGraph", "Edges"] /. Thread[
    Range[Length[embedding]] -> embedding
    ];
Graphics[{
  Point[embedding],
  Line[coords]
  }]

그래픽 대신 이미지에 그리려면 좌표를 다시 조정해야합니다.

toImageCoordinates[{x_, y_}] := {
  Rescale[x, {-1, 1}, {0, 200}],
  Rescale[y, {-1, 1}, {0, 200}]
  }

primitives = Join[
   Point@*toImageCoordinates /@ embedding,
   Line@*toImageCoordinates /@ coords
   ];

이 함수는 광선이있는 모든 기본 요소를 그립니다.

draw[primitive_, size_, glow_] := Module[{bg, img},
  bg = ConstantImage[White, 200];
  img = HighlightImage[bg, {
     Black,
     PointSize[Large],
     Thick,
     primitive
     }];
  ColorNegate@Image[Divide[
      ImageData@DistanceTransform[img],
      size Sqrt[2]
      ]^glow]
  ]

draw[First@primitives, 200, 0.2]

이제 계획은이 함수를 모든 기본 요소에 매핑하는 것입니다.

images = draw[#, 200, 0.2] & /@ primitives;
ImageAdd @@ images // ImageAdjust

이것으로부터 가장자리와 점이 다른 양의 글로우를 가질 수 있음이 분명합니다. 시간 제약으로 인해이 모든 것을 "빛나는 그래프"함수로 통합하는 함수를 만들지는 않을 것이지만이 문제를 해결하기위한 가능한 접근 방식으로 여기에 남겨 둡니다.