Implement arrangement framework for node groups
- Introduced `frames.py` to manage field complex calculations and their arrangement within node groups. - Added functionality to create and remove field frames based on node arrangements. - Developed `passages.py` to find unobstructed paths for connections around calculation frames. - Implemented `references.py` to route shared results on peripheral tracks, ensuring efficient distribution of outputs. - Created `sections.py` to reserve space for field calculations adjacent to geometry consumers. - Added `sources.py` to position shared calculation sources effectively beside their distribution channels. - Enhanced outline smoothing with `outline_smoothing.py` to adapt camera depth along original outlines.
This commit is contained in:
@@ -76,22 +76,33 @@
|
||||
dy = (height - (bottom + top) * scale) / 2;
|
||||
draw();
|
||||
}
|
||||
function updateZoneViews() {
|
||||
view.querySelectorAll('[data-zone]').forEach(option => option.remove());
|
||||
function updateRegionViews() {
|
||||
view.querySelectorAll('[data-zone], [data-frame]').forEach(option => option.remove());
|
||||
current.zones.forEach(zone => {
|
||||
const option = document.createElement('option');
|
||||
option.value = `zone:${zone.entry}`; option.dataset.zone = 'true';
|
||||
option.textContent = `${current.nodes[zone.entry].name} → ${current.nodes[zone.exit].name}`;
|
||||
view.appendChild(option);
|
||||
});
|
||||
current.frames.forEach((frame, index) => {
|
||||
const option = document.createElement('option');
|
||||
option.value = `frame:${index}`; option.dataset.frame = 'true';
|
||||
option.textContent = `Frame · ${frame.title}`;
|
||||
view.appendChild(option);
|
||||
});
|
||||
}
|
||||
function changeView() {
|
||||
selected = null;
|
||||
if (view.value === 'all') {
|
||||
fit(bounds([...current.nodes, ...current.zones]));
|
||||
fit(bounds([...current.nodes, ...current.zones, ...current.frames]));
|
||||
detail.textContent = '完整排列';
|
||||
return;
|
||||
}
|
||||
if (view.value.startsWith('frame:')) {
|
||||
const frame = current.frames[Number(view.value.split(':')[1])];
|
||||
fit(bounds([frame])); detail.textContent = frame.title;
|
||||
return;
|
||||
}
|
||||
if (view.value === 'zone' || view.value.startsWith('zone:')) {
|
||||
if (current.zones.length) {
|
||||
const zones = view.value === 'zone' ? current.zones : current.zones.filter(zone => `zone:${zone.entry}` === view.value);
|
||||
@@ -152,6 +163,17 @@
|
||||
context.strokeStyle = border; context.lineWidth = 1;
|
||||
context.strokeRect(0.5, 0.5, width - 1, height - 1);
|
||||
context.save(); context.beginPath(); context.rect(1, 1, width - 2, height - 2); context.clip();
|
||||
for (const frame of current.frames) {
|
||||
const x = frame.x * scale + dx, y = frame.y * scale + dy;
|
||||
const w = frame.w * scale, h = frame.h * scale;
|
||||
context.fillStyle = '#78909c'; context.globalAlpha = 0.06;
|
||||
context.fillRect(x, y, w, h);
|
||||
context.globalAlpha = 0.5; context.strokeStyle = '#78909c'; context.lineWidth = 1;
|
||||
context.strokeRect(x, y, w, h); context.globalAlpha = 1;
|
||||
if (w > 90 && scale >= 0.15) {
|
||||
context.fillStyle = foreground; label(frame.title, x + 8, y + Math.max(size, 24 * scale), w - 16);
|
||||
}
|
||||
}
|
||||
for (const zone of current.zones) {
|
||||
const x = zone.x * scale + dx, y = zone.y * scale + dy;
|
||||
const w = zone.w * scale, h = zone.h * scale;
|
||||
@@ -236,7 +258,9 @@
|
||||
}
|
||||
picker.addEventListener('change', () => {
|
||||
if (view.value.startsWith('zone:')) view.value = 'zone';
|
||||
current = data[Number(picker.value)]; updateZoneViews(); changeView();
|
||||
current = data[Number(picker.value)]; updateRegionViews();
|
||||
if (!view.value) view.value = 'all';
|
||||
changeView();
|
||||
});
|
||||
view.addEventListener('change', changeView);
|
||||
root.querySelector('#layout-in').addEventListener('click', () => zoom(1.5));
|
||||
@@ -274,6 +298,6 @@
|
||||
}).observe(canvas);
|
||||
new MutationObserver(draw).observe(document.documentElement, { attributes: true, attributeFilter: ['class', 'style', 'data-theme'] });
|
||||
matchMedia('(prefers-color-scheme: dark)').addEventListener('change', draw);
|
||||
updateZoneViews();
|
||||
updateRegionViews();
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user