diff --git a/GDS_SVG_GENERATION_LOGIC.md b/GDS_SVG_GENERATION_LOGIC.md index b1f106b..f50aad4 100644 --- a/GDS_SVG_GENERATION_LOGIC.md +++ b/GDS_SVG_GENERATION_LOGIC.md @@ -25,6 +25,8 @@ Important functions: `../mxpic_router` checkout to `sys.path` when present. - `require_router_stack` (`backend/router_dependency.py` line 31) imports `mxpic_router`, `nazca`, and the route backend used by `mxpic_router`. + The preferred route backend is `mxpic_forge.Route`; if it is absent, + `mxpic_router` falls back to Nazca `interconnects.Interconnect`. `gdstk` is checked only when SVG preview generation requests it. ## Generated Files diff --git a/INTRANET_DEPLOYMENT.md b/INTRANET_DEPLOYMENT.md index 5b5fb4a..b135af9 100644 --- a/INTRANET_DEPLOYMENT.md +++ b/INTRANET_DEPLOYMENT.md @@ -10,8 +10,9 @@ Organization : OptiHK Limited The Flask server can launch for login, dashboard, canvas editing, YAML generation, and PDK browsing without importing `mxpic_router` or `mxpic_forge`. -Build actions require the matched `mxpic_router` and `mxpic_forge` checkouts; -SVG preview generation also requires `gdstk`. +Build actions require `mxpic_router` and Nazca. When `mxpic_forge.Route` is not +available, routing falls back to Nazca `interconnects.Interconnect`; SVG preview +generation also requires `gdstk`. ## Start on the office LAN diff --git a/README.md b/README.md index cae8cf4..79af408 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,9 @@ flask ## Build-Time Router Stack Login, dashboard, canvas editing, YAML generation, and PDK browsing run without -importing `mxpic_router` or `mxpic_forge`. Build actions require the matched -`mxpic_router` and `mxpic_forge` checkouts; SVG preview generation also requires +importing `mxpic_router` or `mxpic_forge`. Build actions require `mxpic_router` +and Nazca. When `mxpic_forge.Route` is unavailable, routing falls back to +Nazca `interconnects.Interconnect`; SVG preview generation also requires `gdstk`. ## PDK and Technology Roots diff --git a/backend/__pycache__/database.cpython-311.pyc b/backend/__pycache__/database.cpython-311.pyc new file mode 100644 index 0000000..7e1cc63 Binary files /dev/null and b/backend/__pycache__/database.cpython-311.pyc differ diff --git a/backend/__pycache__/database.cpython-39.pyc b/backend/__pycache__/database.cpython-39.pyc index 8f3ad1e..0b75b5e 100644 Binary files a/backend/__pycache__/database.cpython-39.pyc and b/backend/__pycache__/database.cpython-39.pyc differ diff --git a/backend/__pycache__/gds_builder.cpython-311.pyc b/backend/__pycache__/gds_builder.cpython-311.pyc new file mode 100644 index 0000000..0debd9a Binary files /dev/null and b/backend/__pycache__/gds_builder.cpython-311.pyc differ diff --git a/backend/__pycache__/gds_builder.cpython-39.pyc b/backend/__pycache__/gds_builder.cpython-39.pyc index 253c0ca..5258156 100644 Binary files a/backend/__pycache__/gds_builder.cpython-39.pyc and b/backend/__pycache__/gds_builder.cpython-39.pyc differ diff --git a/backend/__pycache__/pdk_access.cpython-311.pyc b/backend/__pycache__/pdk_access.cpython-311.pyc new file mode 100644 index 0000000..989f490 Binary files /dev/null and b/backend/__pycache__/pdk_access.cpython-311.pyc differ diff --git a/backend/__pycache__/pdk_access.cpython-39.pyc b/backend/__pycache__/pdk_access.cpython-39.pyc index 3be826e..9c788b4 100644 Binary files a/backend/__pycache__/pdk_access.cpython-39.pyc and b/backend/__pycache__/pdk_access.cpython-39.pyc differ diff --git a/backend/__pycache__/routed_layout_preview.cpython-311.pyc b/backend/__pycache__/routed_layout_preview.cpython-311.pyc new file mode 100644 index 0000000..cf5e986 Binary files /dev/null and b/backend/__pycache__/routed_layout_preview.cpython-311.pyc differ diff --git a/backend/__pycache__/routed_layout_preview.cpython-39.pyc b/backend/__pycache__/routed_layout_preview.cpython-39.pyc index 90c5746..041666a 100644 Binary files a/backend/__pycache__/routed_layout_preview.cpython-39.pyc and b/backend/__pycache__/routed_layout_preview.cpython-39.pyc differ diff --git a/backend/__pycache__/router_dependency.cpython-311.pyc b/backend/__pycache__/router_dependency.cpython-311.pyc new file mode 100644 index 0000000..801b363 Binary files /dev/null and b/backend/__pycache__/router_dependency.cpython-311.pyc differ diff --git a/backend/__pycache__/router_dependency.cpython-39.pyc b/backend/__pycache__/router_dependency.cpython-39.pyc index 5d1181b..c8af590 100644 Binary files a/backend/__pycache__/router_dependency.cpython-39.pyc and b/backend/__pycache__/router_dependency.cpython-39.pyc differ diff --git a/backend/__pycache__/technology_manifest.cpython-311.pyc b/backend/__pycache__/technology_manifest.cpython-311.pyc new file mode 100644 index 0000000..7179b5e Binary files /dev/null and b/backend/__pycache__/technology_manifest.cpython-311.pyc differ diff --git a/backend/__pycache__/technology_manifest.cpython-39.pyc b/backend/__pycache__/technology_manifest.cpython-39.pyc index 8f6c75d..a833997 100644 Binary files a/backend/__pycache__/technology_manifest.cpython-39.pyc and b/backend/__pycache__/technology_manifest.cpython-39.pyc differ diff --git a/backend/router_dependency.py b/backend/router_dependency.py index e7e286f..2fa5f44 100644 --- a/backend/router_dependency.py +++ b/backend/router_dependency.py @@ -60,18 +60,18 @@ def require_router_stack(require_gdstk: bool = False) -> RouterStackStatus: try: router_builder = importlib.import_module("mxpic_router.builder") - route_factory = getattr(router_builder, "_import_mxpic_forge_route") - route_factory() - checked.append("mxpic_forge Route") + route_factory = getattr(router_builder, "_import_route_backend") + route_backend = route_factory() + checked.append(getattr(route_backend, "backend_name", "route backend")) except Exception as exc: - missing.append(f"mxpic_forge Route: {exc}") + missing.append(f"route backend: {exc}") if missing: details = "; ".join(missing) raise RouterStackUnavailable( "Required mxpic_router runtime stack is unavailable. " - "Build actions require the matched mxpic_router and mxpic_forge checkouts, " - f"Nazca, and gdstk for SVG preview generation. Details: {details}" + "Build actions require mxpic_router, Nazca, and either mxpic_forge Route " + f"or the Nazca Interconnect fallback. gdstk is also required for SVG preview generation. Details: {details}" ) return RouterStackStatus(ok=True, router_root=router_root, checked=checked) diff --git a/database/_exports/3ff6e2b43f0d43dab8e169a0b8d6c3d0/mxpic_project_1.gds b/database/_exports/3ff6e2b43f0d43dab8e169a0b8d6c3d0/mxpic_project_1.gds new file mode 100644 index 0000000..ad6500b Binary files /dev/null and b/database/_exports/3ff6e2b43f0d43dab8e169a0b8d6c3d0/mxpic_project_1.gds differ diff --git a/database/admin/layout/mxpic_project_1/mxpic_project_1.svg b/database/admin/layout/mxpic_project_1/mxpic_project_1.svg index 66dc540..0bac00e 100644 --- a/database/admin/layout/mxpic_project_1/mxpic_project_1.svg +++ b/database/admin/layout/mxpic_project_1/mxpic_project_1.svg @@ -1,88 +1,619 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Parameters: +x = 0.0 +y = 4.475 +a = 180.0 +width = 0.7 +name = a1 +Parameters: +x = 0.0 +y = -4.475 +a = 180.0 +width = 0.7 +name = a2 +Parameters: +x = 1660.0 +y = 4.475 +a = 360.0 +width = 0.7 +name = b1 +Parameters: +x = 1660.0 +y = -4.475 +a = 360.0 +width = 0.7 +name = b2 +Parameters: +x = 1660.0 +y = 25.0 +a = 0.0 +width = 5 +name = pin_p +Parameters: +x = 1660.0 +y = 55.0 +a = 0.0 +width = 5 +name = pin_n +Parameters: +x = 1660.0 +y = -25.0 +a = 0.0 +width = 5 +name = ht_s +Parameters: +x = 1660.0 +y = -55.0 +a = 0.0 +width = 5 +name = ht_g + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - + \ No newline at end of file diff --git a/database/admin/layout/mxpic_project_1/mxpic_project_1.yml b/database/admin/layout/mxpic_project_1/mxpic_project_1.yml index 8512327..0607770 100644 --- a/database/admin/layout/mxpic_project_1/mxpic_project_1.yml +++ b/database/admin/layout/mxpic_project_1/mxpic_project_1.yml @@ -25,21 +25,10 @@ pins: # 2. Instances (The sub-components dropped onto this canvas) instances: - MMI_1: - component: Silterra/EMO1_2ML_CU_Al_RDL/primitives/multimode_interferometers/1x2MMI_1310nm_TE_Silterra_202603_ZKY_v2 - x: 557.2 - y: -1888.3 - rotation: 0.0 - flip: 0 - flop: 0 - mirror: false - settings: - length: - - MMI_2: - component: Silterra/EMO1_2ML_CU_Al_RDL/primitives/multimode_interferometers/1x2MMI_1310nm_TE_Silterra_202603_ZKY_v2 - x: 689.2 - y: -1797.5 + MZM_1: + component: Silterra/EMO1_2ML_CU_Al_RDL/composites/Mach_Zender_modulators/MZI_SiN400_Si220_PIN_mod_1310_L1300_QY_202603 + x: 222.2 + y: -473.8 rotation: 0.0 flip: 0 flop: 0 @@ -48,19 +37,6 @@ instances: length: elements: - port: - type: port - x: 50.0 - y: -150.0 - angle: 180.0 - pin_number: 1 - pitch: 10 - layer: WG_CORE - width: 0.5 - description: "" - pins: - - name: port_io1 - role: io1 port: type: port x: 50.0 @@ -80,10 +56,3 @@ bundles: output_bus: routing_type: euler_bend links: - - from: MMI_1:b1 - to: MMI_2:a1 - xsection: strip - family: optical - width: 0.45 - radius: 10 - routing_type: euler_bend \ No newline at end of file diff --git a/database/engineer/layout/mxpic_project_1/canvas_1.svg b/database/engineer/layout/mxpic_project_1/canvas_1.svg new file mode 100644 index 0000000..da409e3 --- /dev/null +++ b/database/engineer/layout/mxpic_project_1/canvas_1.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/database/engineer/layout/mxpic_project_1/canvas_1.yml b/database/engineer/layout/mxpic_project_1/canvas_1.yml new file mode 100644 index 0000000..f890271 --- /dev/null +++ b/database/engineer/layout/mxpic_project_1/canvas_1.yml @@ -0,0 +1,100 @@ +# ============================================= +# mxPIC Cell/Project Definition File +# ============================================= +schema_version: "2.0.0" +kind: cell +coordinate_system: gds_y_up +canvas_size: + width: 5000 + height: 5000 +project: mxpic_project_1 +name: canvas_1 +type: composite +version: "1.0.0" + +# 1. External Ports (How this cell connects to the outside world) +pins: +- name: port_io1 + layer: WG_CORE + element: port + pin: io1 + x: 50.0 + y: -150.0 + angle: 180.0 + width: 0.5 + +# 2. Instances (The sub-components dropped onto this canvas) +instances: + waveguide_1: + component: waveguide + x: 686.5 + y: -1027.9 + rotation: 0.0 + flip: 0 + flop: 0 + mirror: false + settings: + length: 100 + width: 0.5 + xsection: "strip" + + circle_1: + component: circle + x: 877.2 + y: -1093.7 + rotation: 0.0 + flip: 0 + flop: 0 + mirror: false + settings: + radius: 10 + width: 0.5 + xsection: "strip" + + waveguide_2: + component: waveguide + x: 858.0 + y: -1029.6 + rotation: 0.0 + flip: 0 + flop: 0 + mirror: false + settings: + length: 100 + width: 0.5 + xsection: "strip" + +elements: + port: + type: port + x: 50.0 + y: -150.0 + angle: 0.0 + pin_number: 1 + pitch: 10 + layer: WG_CORE + width: 0.5 + description: "" + pins: + - name: port_io1 + role: io1 + +# 3. Bundles (Grouped links for multi-bus/parallel routing) +bundles: + output_bus: + routing_type: euler_bend + links: + - from: waveguide_1:b1 + to: waveguide_2:a1 + xsection: strip + family: optical + width: 0.5 + radius: 10 + routing_type: euler_bend + - from: waveguide_2:b1 + to: circle_1:a1 + xsection: strip + family: optical + width: 0.5 + radius: 10 + routing_type: euler_bend \ No newline at end of file diff --git a/database/engineer/layout/mxpic_project_1/canvas_2.svg b/database/engineer/layout/mxpic_project_1/canvas_2.svg new file mode 100644 index 0000000..30ca134 --- /dev/null +++ b/database/engineer/layout/mxpic_project_1/canvas_2.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/database/engineer/layout/mxpic_project_1/canvas_2.yml b/database/engineer/layout/mxpic_project_1/canvas_2.yml new file mode 100644 index 0000000..6d415b5 --- /dev/null +++ b/database/engineer/layout/mxpic_project_1/canvas_2.yml @@ -0,0 +1,136 @@ +# ============================================= +# mxPIC Cell/Project Definition File +# ============================================= +schema_version: "2.0.0" +kind: cell +coordinate_system: gds_y_up +canvas_size: + width: 5000 + height: 5000 +project: mxpic_project_1 +name: canvas_2 +type: composite +version: "1.0.0" + +# 1. External Ports (How this cell connects to the outside world) +pins: +- name: port_io1 + layer: WG_CORE + element: port + pin: io1 + x: 50.0 + y: -150.0 + angle: 0.0 + width: 0.5 +- name: port_2_io1 + layer: WG_CORE + element: port_2 + pin: io1 + x: 1442.1 + y: -1470.0 + angle: 180.0 + width: 10 +- name: port_3_io1 + layer: WG_CORE + element: port_3 + pin: io1 + x: 2024.3 + y: -1609.0 + angle: 180.0 + width: 0.5 + +# 2. Instances (The sub-components dropped onto this canvas) +instances: + waveguide_3: + component: waveguide + x: 1581.0 + y: -1633.5 + rotation: 0.0 + flip: 0 + flop: 0 + mirror: false + settings: + length: 100 + width: 15 + xsection: "strip" + +elements: + port: + type: port + x: 50.0 + y: -150.0 + angle: 0.0 + pin_number: 1 + pitch: 10 + layer: WG_CORE + width: 0.5 + description: "" + pins: + - name: port_io1 + role: io1 + port: + type: port + x: 50.0 + y: -150.0 + angle: 180.0 + pin_number: 1 + pitch: 10 + layer: WG_CORE + width: 0.5 + description: "" + pins: + - name: port_io1 + role: io1 + port_2: + type: port + x: 1442.1 + y: -1470.0 + angle: 0.0 + pin_number: 1 + pitch: 10 + layer: WG_CORE + width: 10 + description: "" + pins: + - name: port_2_io1 + role: io1 + port_3: + type: port + x: 2024.3 + y: -1609.0 + angle: 0.0 + pin_number: 1 + pitch: 10 + layer: WG_CORE + width: 0.5 + description: "" + pins: + - name: port_3_io1 + role: io1 + +# 3. Bundles (Grouped links for multi-bus/parallel routing) +bundles: + output_bus: + routing_type: euler_bend + links: + - from: waveguide_3:a1 + to: port_2:port_2_io1 + xsection: strip + family: optical + width: 15 + radius: 10 + routing_type: euler_bend + - from: waveguide_3:b1 + to: port_2:port_2_io1 + xsection: strip + family: optical + width: 15 + radius: 10 + routing_type: euler_bend + - from: port_3:port_3_io1 + to: port_2:port_2_io1 + xsection: strip + family: optical + width: 0.5 + radius: 10 + routing_type: euler_bend \ No newline at end of file diff --git a/database/engineer/layout/mxpic_project_1/mxpic_project_1.svg b/database/engineer/layout/mxpic_project_1/mxpic_project_1.svg index ba8ac45..66cda4e 100644 --- a/database/engineer/layout/mxpic_project_1/mxpic_project_1.svg +++ b/database/engineer/layout/mxpic_project_1/mxpic_project_1.svg @@ -1,87 +1,71 @@ - + - - - - - -a1 -b1 -b2 -a0 -b0 + + + + + + + + + + +a1 +a2 +b1 +b2 +pin_p +pin_n +ht_s +ht_g +a0 +b0 - - - - - -a1 -b1 -b2 -a0 -b0 + + + + + + +a0 +b0 +a1 +b1 + + + + + +a1 +b1 +a0 +b0 + + + + + + +a1 +b1 +b2 +a0 +b0 - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + \ No newline at end of file diff --git a/database/engineer/layout/mxpic_project_1/mxpic_project_1.yml b/database/engineer/layout/mxpic_project_1/mxpic_project_1.yml index a4bc821..0fdff0b 100644 --- a/database/engineer/layout/mxpic_project_1/mxpic_project_1.yml +++ b/database/engineer/layout/mxpic_project_1/mxpic_project_1.yml @@ -13,14 +13,79 @@ type: project version: "1.0.0" # 1. External Ports (How this cell connects to the outside world) -ports: [] +pins: +- name: port_1_io1 + layer: WG_CORE + element: port_1 + pin: io1 + x: 1699.6 + y: -1844.2 + angle: 180.0 + width: 0.5 # 2. Instances (The sub-components dropped onto this canvas) instances: + circle_1: + component: circle + x: 1877.6 + y: -1816.7 + rotation: 90.0 + flip: 0 + flop: 0 + mirror: false + settings: + radius: 10 + width: 0.5 + xsection: "strip" + + BD_1: + component: Silterra/EMO1_2ML_CU_Al_RDL/primitives/bendings/SiN_EUB_1310_H400_w2500_L45_QY_202604 + x: 1926.2 + y: -1813.9 + rotation: 90.0 + flip: 0 + flop: 0 + mirror: false + settings: + length: + + DC_1: + component: Silterra/EMO1_2ML_CU_Al_RDL/primitives/directional_couplers/DC_SiN400_99_1_1310_jyh_quantex_202603 + x: 1766.5 + y: -1945.3 + rotation: 0.0 + flip: 0 + flop: 0 + mirror: false + settings: + length: + + MZM_1: + component: Silterra/EMO1_2ML_CU_Al_RDL/composites/Mach_Zender_modulators/MZI_SiN400_Si220_PIN_mod_1310_L1300_QY_202603 + x: 1341.6 + y: -2103.8 + rotation: 0.0 + flip: 0 + flop: 0 + mirror: false + settings: + length: + + phase_shifter_1: + component: Silterra/EMO1_2ML_CU_Al_RDL/primitives/phase_shifters/HT_150R_SiPPP_L500_100OHM_DUMMY_QY_202604 + x: 2695.0 + y: -2275.0 + rotation: 90.0 + flip: 0 + flop: 0 + mirror: false + settings: + length: + MMI_1: component: Silterra/EMO1_2ML_CU_Al_RDL/primitives/multimode_interferometers/1x2MMI_1310nm_TE_Silterra_202603_ZKY_v2 - x: 1511.5 - y: -2531.5 + x: 2849.0 + y: -1988.6 rotation: 0.0 flip: 0 flop: 0 @@ -28,10 +93,10 @@ instances: settings: length: - MMI_2: - component: Silterra/EMO1_2ML_CU_Al_RDL/primitives/multimode_interferometers/1x2MMI_1310nm_TE_Silterra_202603_ZKY_v2 - x: 1716.4 - y: -2293.8 + DC_2: + component: Silterra/EMO1_2ML_CU_Al_RDL/primitives/directional_couplers/DC_SiN400_99_1_1310_jyh_quantex_202603 + x: 2656.9 + y: -1992.8 rotation: 0.0 flip: 0 flop: 0 @@ -39,17 +104,34 @@ instances: settings: length: -elements: {} + PD_1: + component: Silterra/EMO1_2ML_CU_Al_RDL/primitives/photodetectors/PD_1310_Monitor_Si220_Ge500_NPN_XHN_202604 + x: 3151.7 + y: -2032.1 + rotation: 0.0 + flip: 0 + flop: 0 + mirror: false + settings: + length: + +elements: + port_1: + type: port + x: 1699.6 + y: -1844.2 + angle: 0.0 + pin_number: 1 + pitch: 10 + layer: WG_CORE + width: 0.5 + description: "" + pins: + - name: port_1_io1 + role: io1 # 3. Bundles (Grouped links for multi-bus/parallel routing) bundles: output_bus: routing_type: euler_bend links: - - from: MMI_2:a1 - to: MMI_1:b2 - xsection: strip - family: optical - width: 0.45 - radius: 10 - routing_type: euler_bend \ No newline at end of file diff --git a/database/mxpic_data.db b/database/mxpic_data.db index 25ac96b..d29e512 100644 Binary files a/database/mxpic_data.db and b/database/mxpic_data.db differ diff --git a/frontend/canvas-helpers.js b/frontend/canvas-helpers.js index 35fcdbd..16cdde1 100644 --- a/frontend/canvas-helpers.js +++ b/frontend/canvas-helpers.js @@ -42,8 +42,8 @@ name: 'Anchor', elementType: 'anchor', ports: { - a1: { x: 0, y: -PORT_NODE_SIZE / 2, a: 180, width: 0.5 }, - b1: { x: 0, y: -PORT_NODE_SIZE / 2, a: 0, width: 0.5 } + a1: { x: 0, y: 0, a: 180, width: 0.5 }, + b1: { x: 0, y: 0, a: 0, width: 0.5 } } } }; @@ -807,16 +807,13 @@ } }; } - if (portNumber > 1) { - const entries = []; - Array.from({ length: portNumber }, (_, index) => { - const y = elementPortOffset(index, portNumber, pitch); - entries.push([`a${index + 1}`, { x: 0, y, a: 180, width }]); - entries.push([`b${index + 1}`, { x: 0, y, a: 0, width }]); - }); - return Object.fromEntries(entries); - } - return JSON.parse(JSON.stringify(element.ports)); + const entries = []; + Array.from({ length: portNumber }, (_, index) => { + const y = elementPortOffset(index, portNumber, pitch); + entries.push([`a${index + 1}`, { x: 0, y, a: 180, width }]); + entries.push([`b${index + 1}`, { x: 0, y, a: 0, width }]); + }); + return Object.fromEntries(entries); }; // Generate port metadata for built-in primitive components. diff --git a/frontend/canvas.html b/frontend/canvas.html index 1b40d3b..a33f56e 100644 --- a/frontend/canvas.html +++ b/frontend/canvas.html @@ -1721,7 +1721,7 @@ Organization : OptiHK Limited }; const componentSize = normalizeBoxSize({ box_size: data.boxSize }, DEFAULT_COMPONENT_BOX_SIZE); const portHandles = useMemo( - () => buildPortHandles(data.ports, { rotation: data.rotation || 0, flip: Boolean(data.flip), flop: Boolean(data.flop), boxSize: componentSize }), + () => buildPortHandles(data.ports, { rotation: 0, flip: Boolean(data.flip), flop: Boolean(data.flop), boxSize: componentSize }), [data.ports, data.rotation, data.flip, data.flop, componentSize] ); const portDirectionMap = useMemo( @@ -1735,16 +1735,17 @@ Organization : OptiHK Limited const iconSize = createComponentSymbolMetrics(componentSize); const portLabelStyle = (portHandle) => { const base = { ...portHandle.style }; + const unrotate = `rotate(${-(data.rotation || 0)}deg) scaleX(${data.flop ? -1 : 1}) scaleY(${data.flip ? -1 : 1})`; if (portHandle.position === 'left') { - return { ...base, left: 'auto', right: 'calc(100% + 8px)', transform: 'translateY(-50%)', textAlign: 'right' }; + return { ...base, left: 'auto', right: 'calc(100% + 8px)', transform: `translateY(-50%) ${unrotate}`, textAlign: 'right' }; } if (portHandle.position === 'right') { - return { ...base, left: 'calc(100% + 8px)', right: 'auto', transform: 'translateY(-50%)', textAlign: 'left' }; + return { ...base, left: 'calc(100% + 8px)', right: 'auto', transform: `translateY(-50%) ${unrotate}`, textAlign: 'left' }; } if (portHandle.position === 'top') { - return { ...base, top: 'auto', bottom: 'calc(100% + 8px)', transform: 'translateX(-50%)', textAlign: 'center' }; + return { ...base, top: 'auto', bottom: 'calc(100% + 8px)', transform: `translateX(-50%) ${unrotate}`, textAlign: 'center' }; } - return { ...base, top: 'calc(100% + 8px)', bottom: 'auto', transform: 'translateX(-50%)', textAlign: 'center' }; + return { ...base, top: 'calc(100% + 8px)', bottom: 'auto', transform: `translateX(-50%) ${unrotate}`, textAlign: 'center' }; }; return ( @@ -1758,79 +1759,85 @@ Organization : OptiHK Limited {data.componentName} )} -
- {isAnchorElement ? ( - A - ) : ( -
- {!data.hideIcon && data.category && ( -
- +
+
+ {isAnchorElement ? ( + A + ) : ( +
+ {!data.hideIcon && data.category && ( +
+ +
+ )} + {!data.category &&
}
)} - {!data.category &&
} -
- )} -
+
+ +
+ {portHandles.map((portHandle) => ( + + + + + ))} +
-
{portHandles.map((portHandle) => ( - - - + + + {portHandle.name} + ))}
- - {portHandles.map((portHandle) => ( - - - {portHandle.name} - - - ))}
); }, (prevProps, nextProps) => { @@ -1985,29 +1992,22 @@ Organization : OptiHK Limited const name = String(portName || ''); return name.startsWith('a') || name.startsWith('left') ? 'left' : 'right'; }; - const anchorHandleVisualStyle = (portHandle, zIndex) => { - const visualSide = anchorPortVisualSide(portHandle.name); - const localLeft = visualSide === 'left' ? 0 : elementSize.width; - const localTop = portHandle.style?.top || '50%'; - return { - ...baseHandleStyle, - zIndex, - left: localLeft, - top: localTop, - right: 'auto', - bottom: 'auto', - transform: 'translate(-50%, -50%)' - }; - }; + const anchorHandleVisualStyle = (portHandle, zIndex) => ({ + ...baseHandleStyle, + zIndex, + left: portHandle.style?.left, + top: portHandle.style?.top || '50%', + right: portHandle.style?.right || 'auto', + bottom: portHandle.style?.bottom || 'auto', + transform: portHandle.style?.transform || 'translate(-50%, -50%)' + }); const pinLabelStyle = (portHandle) => { const visualSide = anchorPortVisualSide(portHandle.name); - const localLeft = visualSide === 'left' ? 0 : elementSize.width; - const localTop = portHandle.style?.top || '50%'; return { - left: localLeft, - top: localTop, - right: 'auto', - bottom: 'auto', + left: portHandle.style?.left, + top: portHandle.style?.top || '50%', + right: portHandle.style?.right || 'auto', + bottom: portHandle.style?.bottom || 'auto', transform: visualSide === 'left' ? 'translate(calc(-100% - 5px), -50%)' : 'translate(5px, -50%)' }; }; @@ -3359,6 +3359,7 @@ Organization : OptiHK Limited const forge = isForgeComponent(componentName); onUpdateNode(selectedNode.id, { data: { + ...selectedNode.data, componentName, label: componentName, ports: forge ? {} : undefined, diff --git a/tests/layout-backend-static.test.js b/tests/layout-backend-static.test.js index a2d1582..9721715 100644 --- a/tests/layout-backend-static.test.js +++ b/tests/layout-backend-static.test.js @@ -132,7 +132,7 @@ assert( routerDependencyPy.includes('require_gdstk: bool = False') && routerDependencyPy.includes('importlib.import_module("nazca")') && routerDependencyPy.includes('mxpic_router.builder') && - routerDependencyPy.includes('_import_mxpic_forge_route'), + routerDependencyPy.includes('_import_route_backend'), 'router dependency gate should validate mxpic_router, Nazca, optional gdstk, and route backend imports' ); @@ -151,7 +151,9 @@ if (fs.existsSync(routerDir)) { routerBuilderPy.includes('_port_element_pin_entries') && routerBuilderPy.includes('_anchor_element_pin_entries') && routerBuilderPy.includes('_metadata_pins') && - routerBuilderPy.includes('link.src_pin'), + routerBuilderPy.includes('link.src_pin') && + routerBuilderPy.includes('_NazcaInterconnectRoute') && + routerBuilderPy.includes('_import_route_backend'), 'mxpic_router builder should register named element pins and route through pin endpoints' ); } diff --git a/work _log.md b/work _log.md index 5d5dc75..7ae6fa2 100644 --- a/work _log.md +++ b/work _log.md @@ -2,4 +2,10 @@ 1.Fixed an issue where switching between different tabs would automatically reset the zoom level. -2.Fixed an port width mismatch in YAML bundles. \ No newline at end of file +2.Fixed an port width mismatch in YAML bundles. + +3.Fixed the issue where SVG were displaying in incorrect positions. + +4.Fixed the abnormal port shift after rotation. + +5.Fixed the abnormal position of individual ports. \ No newline at end of file