Forge
csharpdeeb25a2
1#nullable enable
2using CascadeIDE.Models;
3
4namespace CascadeIDE.Cockpit.Graph.Layout;
5
6/// <summary>Геометрия related-files на карте намерений (уровень file).</summary>
7public static class GraphFileLayoutMetrics
8{
9 public const double SideLabelMargin = 68;
10 public const double DefaultHeightFile = GraphViewportMetrics.DefaultHeightFile;
11 public const double MaxHeightFile = 380;
12 public const double MaxHeightHierarchy = 520;
13
14 public static double EstimatePreferredHeight(
15 int satelliteCount,
16 CodeNavigationMapDetailLevel detailLevel,
17 string relatedLayout)
18 {
19 if (satelliteCount <= 0)
20 return DefaultHeightFile;
21
22 var layout = CodeNavigationMapRelatedGraphLayoutKind.Normalize(relatedLayout);
23 if (CodeNavigationMapRelatedGraphLayoutKind.IsHierarchy(layout))
24 return EstimateHierarchyHeight(satelliteCount, detailLevel);
25
26 if (satelliteCount <= 8)
27 return DefaultHeightFile;
28
29 var perSatellite = detailLevel switch
30 {
31 CodeNavigationMapDetailLevel.Glance => 3.5,
32 CodeNavigationMapDetailLevel.Inspect => 7.5,
33 _ => 5.5
34 };
35 var extra = (satelliteCount - 8) * perSatellite;
36 return Math.Clamp(DefaultHeightFile + extra, DefaultHeightFile, MaxHeightFile);
37 }
38
39 public static double EstimateHierarchyHeight(int satelliteCount, CodeNavigationMapDetailLevel detailLevel)
40 {
41 var perRow = detailLevel switch
42 {
43 CodeNavigationMapDetailLevel.Glance => 34,
44 CodeNavigationMapDetailLevel.Inspect => 44,
45 _ => 38
46 };
47 var rows = 1 + Math.Max(0, satelliteCount);
48 return Math.Clamp(72 + rows * perRow, DefaultHeightFile, MaxHeightHierarchy);
49 }
50
51 /// <summary>Радиусы внутренней и внешней орбит (режим <c>radial</c>).</summary>
52 public static (double Inner, double Outer) ResolveRadialOrbits(
53 int satelliteCount,
54 double innerWidth,
55 double innerHeight,
56 double satelliteRadius)
57 {
58 var minInner = Math.Min(innerWidth, innerHeight);
59 var extent = Math.Sqrt(Math.Max(1, innerWidth * innerHeight));
60 var wantTwoRings = satelliteCount > 8;
61 var densityBoost = 1.0 + Math.Max(0, satelliteCount - 6) * 0.042;
62 var maxOuterOrbit = Math.Max(32, minInner * 0.50 - satelliteRadius);
63 var desired = extent * (wantTwoRings ? 0.40 : 0.44) * densityBoost;
64 var useTwoRings = wantTwoRings && maxOuterOrbit >= 56;
65
66 if (!useTwoRings)
67 {
68 var orbit = ClampOrMin(desired, 26, maxOuterOrbit);
69 return (orbit, orbit);
70 }
71
72 var maxInnerOrbit = Math.Max(26, maxOuterOrbit - satelliteRadius * 3.2 - 14);
73 var orbitInner = ClampOrMin(desired * 0.9, 26, maxInnerOrbit);
74 var orbitOuterDesired = Math.Max(
75 orbitInner + satelliteRadius * 2.6 + 14,
76 extent * 0.52 * densityBoost);
77 var orbitOuter = ClampOrMin(
78 orbitOuterDesired,
79 orbitInner + satelliteRadius + 8,
80 maxOuterOrbit);
81 return (orbitInner, orbitOuter);
82 }
83
84 private static double ClampOrMin(double value, double min, double max) =>
85 max < min ? min : Math.Clamp(value, min, max);
86}
87
View only · write via MCP/CIDE