archgraph-layout 2.0.1__tar.gz → 2.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {archgraph_layout-2.0.1/archgraph_layout.egg-info → archgraph_layout-2.0.2}/PKG-INFO +1 -1
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/__init__.py +1 -1
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/engine.py +4 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/hierarchy.py +4 -0
- archgraph_layout-2.0.2/archgraph/placement/notes.py +81 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2/archgraph_layout.egg-info}/PKG-INFO +1 -1
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph_layout.egg-info/SOURCES.txt +1 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/docs/xml-reference.md +4 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/halcyon7.xml +1 -22
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/LICENSE +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/MANIFEST.in +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/README.md +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/__main__.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/cli.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/geometry.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/model.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/parser.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/__init__.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/congestion.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/detail.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/floorplan.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/graphalgo.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/layered.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/ports.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/sizing.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/placement/vpsc.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/portlabels.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/progress.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/quality.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/render/__init__.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/render/html.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/render/jsonout.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/render/png.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/render/shapes.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/render/svg.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/routing/__init__.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/routing/grid.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/routing/nudge.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/routing/router.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/shapegeometry.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/styles.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph/textmetrics.py +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph_layout.egg-info/dependency_links.txt +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph_layout.egg-info/entry_points.txt +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph_layout.egg-info/requires.txt +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph_layout.egg-info/top_level.txt +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/accelerator_mesh.xml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/automotive.xml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/basic.xml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/datacenter.xml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/flat_network.xml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/fpga_pipeline.xml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/halcyon7_lib.xml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/halcyon7_styles.xml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/examples/soc.xml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/pyproject.toml +0 -0
- {archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/setup.cfg +0 -0
|
@@ -23,7 +23,7 @@ from .progress import report
|
|
|
23
23
|
from .placement import engine as _engine # noqa: E402
|
|
24
24
|
from . import routing as _routing # noqa: E402
|
|
25
25
|
|
|
26
|
-
__version__ = "2.0.
|
|
26
|
+
__version__ = "2.0.2"
|
|
27
27
|
__all__ = ["load", "loads", "layout", "route", "build", "to_svg", "to_html", "to_json", "to_png", "save",
|
|
28
28
|
"ArchGraphError", "Graph", "__version__"]
|
|
29
29
|
|
|
@@ -11,6 +11,7 @@ from . import sizing
|
|
|
11
11
|
from .hierarchy import (HierarchicalPlacer, apply_keep_together, auto_cluster, build_layout_edges, lift_hints,
|
|
12
12
|
translate_element)
|
|
13
13
|
from .ports import assign_ports, distribute_ports, slide_ports
|
|
14
|
+
from .notes import compact_notes
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def unify_instances(g: Graph) -> int:
|
|
@@ -85,6 +86,9 @@ def finish_ports(g: Graph, placer):
|
|
|
85
86
|
assign_ports(g, slide=False)
|
|
86
87
|
if g.settings.align_edges:
|
|
87
88
|
placer.topdown(g.root)
|
|
89
|
+
if compact_notes(g):
|
|
90
|
+
# A relocated annotation may now face a different side of its target.
|
|
91
|
+
assign_ports(g, slide=False)
|
|
88
92
|
distribute_ports(g)
|
|
89
93
|
slide_ports(g)
|
|
90
94
|
normalize(g)
|
|
@@ -92,6 +92,10 @@ def build_layout_edges(g: Graph) -> List[LEdge]:
|
|
|
92
92
|
a, b = e.src.element, e.dst.element
|
|
93
93
|
flow = e.constraint and e.directed and "__note__" not in e.classes
|
|
94
94
|
w = e.weight * (1.0 + 0.15 * (e.multiplicity - 1))
|
|
95
|
+
if "__note__" in e.classes:
|
|
96
|
+
# Annotations should stay with their subject. They remain auxiliary
|
|
97
|
+
# edges so they impose no signal flow, crossings or hard alignment.
|
|
98
|
+
w *= 6.0
|
|
95
99
|
le = LEdge(a, e.src.port, b, e.dst.port, w, flow, e.straight, e)
|
|
96
100
|
le.aux = "__note__" in e.classes
|
|
97
101
|
le.scope = g.edge_scope(a, b)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Move targeted annotations into nearby free space without moving circuit blocks."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from ..geometry import Rect
|
|
5
|
+
from ..model import Graph, Node, Subsystem
|
|
6
|
+
from ..portlabels import port_label_geometry, port_text_size
|
|
7
|
+
from .sizing import subsystem_padding
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _distance(note: Rect, target: Rect):
|
|
11
|
+
dx = max(target.x0-note.x1, note.x0-target.x1, 0)
|
|
12
|
+
dy = max(target.y0-note.y1, note.y0-target.y1, 0)
|
|
13
|
+
# Prefer a short leader and alignment with the target, including when the
|
|
14
|
+
# target is a large subsystem with many equally close boundary positions.
|
|
15
|
+
return dx+dy+.08*(abs(note.cx-target.cx)+abs(note.cy-target.cy))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def compact_notes(g: Graph) -> int:
|
|
19
|
+
"""Improve note proximity within the existing parent frame and free gaps.
|
|
20
|
+
|
|
21
|
+
Detailed placement preserves sibling ordering. An annotation can instead
|
|
22
|
+
move around a sibling into a closer gap, provided it covers no other block
|
|
23
|
+
or external port name. Explicit hints and table layouts keep their positions.
|
|
24
|
+
"""
|
|
25
|
+
pinned = {el for hint in g.hints for el in hint.elements}
|
|
26
|
+
links = [e for e in g.edges if "__note__" in e.classes and
|
|
27
|
+
isinstance(e.src.element, Node) and e.src.element.is_note]
|
|
28
|
+
moved = set()
|
|
29
|
+
for _ in range(2):
|
|
30
|
+
changed = False
|
|
31
|
+
for edge in links:
|
|
32
|
+
note, target = edge.src.element, edge.dst.element
|
|
33
|
+
parent = note.parent
|
|
34
|
+
if parent is None or note in pinned or parent.algorithm in ("row", "column", "grid", "layered"):
|
|
35
|
+
continue
|
|
36
|
+
spacing = parent.spacing if parent.spacing is not None else g.settings.node_spacing
|
|
37
|
+
gap = max(spacing, 2*g.settings.node_margin+g.settings.edge_spacing)
|
|
38
|
+
pad = 0 if parent is g.root else subsystem_padding(parent, g.settings)
|
|
39
|
+
frame = parent.rect
|
|
40
|
+
bounds = Rect(frame.x0+pad, frame.y0+pad+parent.header_h,
|
|
41
|
+
frame.x1-pad, frame.y1-pad)
|
|
42
|
+
if bounds.w < note.w or bounds.h < note.h:
|
|
43
|
+
continue
|
|
44
|
+
obstacles = []
|
|
45
|
+
for sibling in parent.children:
|
|
46
|
+
if sibling is note:
|
|
47
|
+
continue
|
|
48
|
+
obstacles.append(sibling.rect.inflate(gap))
|
|
49
|
+
if isinstance(sibling, Subsystem) and sibling.visible:
|
|
50
|
+
for p in sibling.ports.values():
|
|
51
|
+
if port_text_size(p, g.settings) != (0.0, 0.0):
|
|
52
|
+
obstacles.append(port_label_geometry(p, g.settings, False)[3].inflate(8))
|
|
53
|
+
hw, hh = note.w/2, note.h/2
|
|
54
|
+
xs = {note.x, target.x, bounds.x0+hw, bounds.x1-hw,
|
|
55
|
+
target.rect.x0-hw-gap, target.rect.x1+hw+gap}
|
|
56
|
+
ys = {note.y, target.y, bounds.y0+hh, bounds.y1-hh,
|
|
57
|
+
target.rect.y0-hh-gap, target.rect.y1+hh+gap}
|
|
58
|
+
for ob in obstacles:
|
|
59
|
+
xs.update((ob.x0-hw, ob.x1+hw))
|
|
60
|
+
ys.update((ob.y0-hh, ob.y1+hh))
|
|
61
|
+
xs = [x for x in xs if bounds.x0+hw-1e-6 <= x <= bounds.x1-hw+1e-6]
|
|
62
|
+
ys = [y for y in ys if bounds.y0+hh-1e-6 <= y <= bounds.y1-hh+1e-6]
|
|
63
|
+
current = _distance(note.rect, target.rect)
|
|
64
|
+
candidates = []
|
|
65
|
+
for x in xs:
|
|
66
|
+
for y in ys:
|
|
67
|
+
r = Rect.from_center(x, y, note.w, note.h)
|
|
68
|
+
distance = _distance(r, target.rect)
|
|
69
|
+
if distance < current-.5:
|
|
70
|
+
candidates.append((distance, abs(x-note.x)+abs(y-note.y), x, y, r))
|
|
71
|
+
candidates.sort(key=lambda c: c[:4])
|
|
72
|
+
for _, _, x, y, r in candidates:
|
|
73
|
+
if any(r.overlaps(ob) for ob in obstacles):
|
|
74
|
+
continue
|
|
75
|
+
note.x, note.y = x, y
|
|
76
|
+
moved.add(note)
|
|
77
|
+
changed = True
|
|
78
|
+
break
|
|
79
|
+
if not changed:
|
|
80
|
+
break
|
|
81
|
+
return len(moved)
|
|
@@ -22,6 +22,7 @@ archgraph/placement/floorplan.py
|
|
|
22
22
|
archgraph/placement/graphalgo.py
|
|
23
23
|
archgraph/placement/hierarchy.py
|
|
24
24
|
archgraph/placement/layered.py
|
|
25
|
+
archgraph/placement/notes.py
|
|
25
26
|
archgraph/placement/ports.py
|
|
26
27
|
archgraph/placement/sizing.py
|
|
27
28
|
archgraph/placement/vpsc.py
|
|
@@ -509,6 +509,10 @@ A note without `target` is a free-standing annotation in its enclosing
|
|
|
509
509
|
subsystem. A targeted note normally shares its target's parent; use
|
|
510
510
|
`inside="true"` to place a note inside a target subsystem. `id`, `width`, `class`,
|
|
511
511
|
`fill`, and `text` optionally customize the note.
|
|
512
|
+
Targeted notes prefer nearby open space and can move around sibling blocks to
|
|
513
|
+
shorten their dotted leader. They keep the configured spacing, stay inside their
|
|
514
|
+
parent, and avoid external port labels. Explicit layout hints involving a note
|
|
515
|
+
and table/row/column layouts retain their placement.
|
|
512
516
|
|
|
513
517
|
`legend="auto"` uses classes with a `legend` attribute. Explicit `<legend><entry
|
|
514
518
|
.../></legend>` entries switch the default auto mode to `always`. Set
|
|
@@ -1,26 +1,5 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
|
|
3
|
-
╔══════════════════════════════════════════════════════════════════════╗
|
|
4
|
-
║ HALCYON-7 · agile X-band SAR constellation node ("dark-vessel hunter") ║
|
|
5
|
-
╚══════════════════════════════════════════════════════════════════════╝
|
|
6
|
-
Mission: image the ocean through cloud and night with a 64-element digital-
|
|
7
|
-
beamforming SAR, focus the raw echoes on board, find ships with a CNN, match
|
|
8
|
-
them against AIS, and flag the ones running dark. Alerts reach peers over
|
|
9
|
-
10 Gbps laser crosslinks and reach the ground in minutes, not hours.
|
|
10
|
-
|
|
11
|
-
Architecture is real-world shaped (ESA-style regulated 28 V bus, GR740 OBC,
|
|
12
|
-
SpaceWire/SpaceFibre, CMG agility, Hall EP); the spacecraft is fictional.
|
|
13
|
-
|
|
14
|
-
Files (keep together, includes are relative):
|
|
15
|
-
halcyon7.xml ← this file
|
|
16
|
-
halcyon7_lib.xml ← templates; includes ↓
|
|
17
|
-
halcyon7_styles.xml ← classes
|
|
18
|
-
|
|
19
|
-
Stress knobs: PANELS / TILES / TRMS scale the phased array (PANELS*TILES*TRMS
|
|
20
|
-
T/R modules, ~5 nodes and ~5 edges each). CMGS, HEADS, BMODS, RCS, WING_PANELS
|
|
21
|
-
scale the rest.
|
|
22
|
-
-->
|
|
23
|
-
<archgraph title="HALCYON-7 · Dark-Vessel Hunter"
|
|
2
|
+
<archgraph title="HALCYON-7"
|
|
24
3
|
direction="LR" aspect="16:9" theme="blueprint" quality="high" seed="1337"
|
|
25
4
|
author="archgraph stress test" revision="C2" date="2026-10-10">
|
|
26
5
|
<subtitle>Agile X-band DBF-SAR · on-board AI · 10 Gbps laser crosslinks · SSO 520 km dawn-dusk</subtitle>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph_layout.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{archgraph_layout-2.0.1 → archgraph_layout-2.0.2}/archgraph_layout.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|