กราฟถ่วงน้ำหนักเรืองแสง (เครือข่าย): จุดยอดและขอบ
ฉันกำลังพยายามหาวิธี (เรียบง่ายและประสิทธิภาพ / ความเร็วที่ดีที่สุดสำหรับกราฟขนาดใหญ่) เพื่อทำสิ่งต่อไปนี้:
จุดยอดกราฟจัดแต่งทรงผมตามเอฟเฟกต์เรืองแสงและความเข้มขึ้นอยู่กับ
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}]]]]]

ขอบคุณความช่วยเหลือของคุณจะได้รับการชื่นชมอย่างมาก!
คำตอบ
คุณสามารถรับเอฟเฟกต์การเรืองแสงโดยรวมได้โดยImageAdd
สำเนาเบลอของมาสก์รูปภาพ เป็นที่ยอมรับว่ามันค่อนข้างธรรมดา แต่เอฟเฟกต์นั้นน่าสนใจ ฉันเลือกที่จะสร้างเครือข่าย 'สมอง' โดยใช้AnatomyData
และNearestNeighbourGraph
ทำให้ดูเหมือนเป็นการตลาด 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]]]]
เพื่อให้ได้น้ำหนักที่จะส่งผลกระทบต่อขนาดของเรืองแสงคุณอาจจะต้องใช้และEdgeShapeFunction
VertexShapeFunction
ฉันสร้างพื้นผิวป้ายโฆษณาของเอฟเฟกต์เลนส์ด้วยอัลฟาและฉันใช้ภาพนี้สำหรับจุดยอด:
ฉันยังใช้เอฟเฟกต์การเรืองแสงที่ขอบที่คุณพูดถึงในคำถามที่ซ้อนเส้น ขอบที่มีน้ำหนักมากกว่าควรมีการเรืองแสงมากขึ้นและจุดยอดที่มีน้ำหนักมากกว่าจะมีแสงแฟลร์ขนาดใหญ่:
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]

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

จากสิ่งนี้เห็นได้ชัดว่าขอบและจุดต่างๆอาจมีปริมาณแสงที่แตกต่างกัน เนื่องจากข้อ จำกัด ด้านเวลาฉันจะไม่ทำให้ฟังก์ชันที่รวมทั้งหมดนี้เข้าด้วยกันเป็นฟังก์ชัน "กราฟเรืองแสง" แต่ฉันปล่อยให้สิ่งนี้เป็นแนวทางที่เป็นไปได้ในการแก้ปัญหานี้