import { useId } from "react";
import {
SYMBOL_ACCENT,
SYMBOL_FILL,
SYMBOL_STROKE,
SymbolSvg,
} from "./primitives";
import type { ComponentSymbolRendererProps } from "./types";
const MECHANICAL_LINE_WIDTH = 1.8;
const MECMAS21_STROKE = "#00af00";
const MECMAS21_HATCH = "#66cf66";
const MECMAS21_FILL = "#ffffff";
const MECMAS21_CONTENT_SCALE = 0.72;
const MECMAS21_CONTENT_CENTER = { x: 32, y: 24 } as const;
const MECMAS21_CONTENT_TRANSFORM = `translate(${MECMAS21_CONTENT_CENTER.x} ${MECMAS21_CONTENT_CENTER.y}) scale(${MECMAS21_CONTENT_SCALE}) translate(${-MECMAS21_CONTENT_CENTER.x} ${-MECMAS21_CONTENT_CENTER.y})`;
const MECMAS21_SELECTION_ENVELOPE = {
x: 9.608,
y: 2.328,
width: 44.784,
height: 43.344,
} as const;
const F000_CONTENT_SCALE = 0.25;
const F000_CONTENT_CENTER = { x: 32, y: 24 } as const;
const F000_CONTENT_TRANSFORM = `translate(${F000_CONTENT_CENTER.x} ${F000_CONTENT_CENTER.y}) scale(${F000_CONTENT_SCALE}) translate(${-F000_CONTENT_CENTER.x} ${-F000_CONTENT_CENTER.y})`;
const F000_FRAME_RIGHT_X =
F000_CONTENT_CENTER.x +
(52 - F000_CONTENT_CENTER.x) * F000_CONTENT_SCALE;
export const F000_PORT_ANCHOR = {
x: 48,
y: 24,
} as const;
const FORC_STROKE = "#00af00";
const FORC_CONTENT_SCALE = 0.64;
const FORC_CONTENT_CENTER = { x: 32, y: 24 } as const;
const FORC_CONTENT_TRANSFORM = `translate(${FORC_CONTENT_CENTER.x} ${FORC_CONTENT_CENTER.y}) scale(${FORC_CONTENT_SCALE}) translate(${-FORC_CONTENT_CENTER.x} ${-FORC_CONTENT_CENTER.y})`;
export const FORC_PORT_ANCHORS = {
left: {
x:
FORC_CONTENT_CENTER.x +
(2 - FORC_CONTENT_CENTER.x) * FORC_CONTENT_SCALE,
y: FORC_CONTENT_CENTER.y,
},
right: {
x:
FORC_CONTENT_CENTER.x +
(62 - FORC_CONTENT_CENTER.x) * FORC_CONTENT_SCALE,
y: FORC_CONTENT_CENTER.y,
},
} as const;
export const MECMAS21_PORT_ANCHORS = {
left: {
x:
MECMAS21_CONTENT_CENTER.x +
(2 - MECMAS21_CONTENT_CENTER.x) * MECMAS21_CONTENT_SCALE,
y: 24,
},
right: {
x:
MECMAS21_CONTENT_CENTER.x +
(62 - MECMAS21_CONTENT_CENTER.x) * MECMAS21_CONTENT_SCALE,
y: 24,
},
} as const;
const LSTP00A_STROKE = "#00af00";
const LSTP00A_STROKE_WIDTH = 3;
const LSTP00A_CONTENT_SCALE = (64 * 0.65) / 60;
const LSTP00A_CONTENT_CENTER = { x: 32, y: 24 } as const;
const LSTP00A_CONTENT_TRANSFORM = `translate(${LSTP00A_CONTENT_CENTER.x} ${LSTP00A_CONTENT_CENTER.y}) scale(${LSTP00A_CONTENT_SCALE}) translate(${-LSTP00A_CONTENT_CENTER.x} ${-LSTP00A_CONTENT_CENTER.y})`;
export const LSTP00A_PORT_ANCHORS = {
left: {
x:
LSTP00A_CONTENT_CENTER.x +
(2 - LSTP00A_CONTENT_CENTER.x) * LSTP00A_CONTENT_SCALE,
y: LSTP00A_CONTENT_CENTER.y,
},
right: {
x:
LSTP00A_CONTENT_CENTER.x +
(62 - LSTP00A_CONTENT_CENTER.x) * LSTP00A_CONTENT_SCALE,
y: LSTP00A_CONTENT_CENTER.y,
},
} as const;
const PNRP17_STROKE = "#8b134f";
const PNRP17_FILL = "#cf9db6";
const PNRP17_LIGHT_FILL = "#f5ebf0";
// PNRP17 使用最终像素线宽;几何缩放不再改变参考图中的粗细层级。
const PNRP17_PRIMARY_STROKE_WIDTH = 2.1;
const PNRP17_DETAIL_STROKE_WIDTH = 1.9;
const PNRP17_VERTICAL_CENTER = 24.5;
const PNRP17_VERTICAL_SCALE = 1.21;
const PNRP17_CONTENT_TRANSFORM = `translate(0 ${PNRP17_VERTICAL_CENTER}) scale(1 ${PNRP17_VERTICAL_SCALE}) translate(0 ${-PNRP17_VERTICAL_CENTER})`;
const pnrp17ScaledY = (y: number) =>
PNRP17_VERTICAL_CENTER +
(y - PNRP17_VERTICAL_CENTER) * PNRP17_VERTICAL_SCALE;
export const PNRP17_PORT_ANCHORS = {
bottom: { x: 25.5, y: pnrp17ScaledY(48) },
upperLeft: { x: 2, y: pnrp17ScaledY(4.4) },
middleLeft: { x: 2, y: pnrp17ScaledY(24.1) },
upperRight: { x: 62, y: pnrp17ScaledY(4.4) },
middleRight: { x: 62, y: pnrp17ScaledY(24.1) },
} as const;
const mechanicalStroke = {
fill: "none",
stroke: SYMBOL_STROKE,
strokeLinecap: "round" as const,
strokeLinejoin: "round" as const,
strokeWidth: MECHANICAL_LINE_WIDTH,
};
function MechanicalSocket({ side }: { side: "left" | "right" }) {
const facingLeft = side === "left";
return (
);
}
export function AmesimF000Symbol() {
return (
);
}
export function AmesimForcSymbol() {
return (
F
);
}
export function AmesimMecmas21Symbol({
parameters,
}: ComponentSymbolRendererProps) {
const frictionEnabled = Number(parameters?.useFriction ?? 2) === 2;
const stopType = Number(parameters?.stoptype ?? 1);
const limitsEnabled = stopType === 1 || stopType === 2 || stopType === 3;
const showGuides = frictionEnabled || limitsEnabled;
const variant = frictionEnabled
? limitsEnabled
? "friction-limited"
: "friction-unlimited"
: limitsEnabled
? "plain-limited"
: "plain-unlimited";
const hatchingId = `mecmas21-hatching-${useId().replace(
/[^a-zA-Z0-9_-]/g,
"",
)}`;
return (
{showGuides ? (
{limitsEnabled ? (
) : (
)}
) : null}
{frictionEnabled ? (
) : null}
M
{/* 固定选择包络:参数切换为仅中央滑块时,虚线框仍保持完整状态大小。 */}
);
}
export function AmesimLstp00aSymbol() {
return (
);
}
export const LMECHN1_DEFAULT_RIGHT_PORT_COUNT = 2;
export const LMECHN1_MAX_RIGHT_PORT_COUNT = 20;
const LMECHN1_PALETTE_RIGHT_PORT_COUNT = 5;
const LMECHN1_PORT_ROW_SPACING = 13;
const LMECHN1_BODY_LEFT = 18;
const LMECHN1_BODY_RIGHT = 46;
const LMECHN1_SOCKET_WIDTH = 6;
const LMECHN1_SOCKET_HALF_HEIGHT = 2.5;
const LMECHN1_LEFT_SOCKET_OUTER_X = LMECHN1_BODY_LEFT - LMECHN1_SOCKET_WIDTH;
const LMECHN1_RIGHT_SOCKET_OUTER_X = LMECHN1_BODY_RIGHT + LMECHN1_SOCKET_WIDTH;
export function lmechn1RightPortCount(
parameters?: ComponentSymbolRendererProps["parameters"],
) {
const candidate = Number(parameters?.v1);
if (!Number.isInteger(candidate)) {
return LMECHN1_DEFAULT_RIGHT_PORT_COUNT;
}
return Math.min(
LMECHN1_MAX_RIGHT_PORT_COUNT,
Math.max(1, candidate),
);
}
export function lmechn1SymbolMetrics(
parameters?: ComponentSymbolRendererProps["parameters"],
) {
const rightPortCount = lmechn1RightPortCount(parameters);
const requestedBodyHeight = Math.max(
28,
12 + (rightPortCount - 1) * LMECHN1_PORT_ROW_SPACING,
);
const viewBoxHeight = Math.max(48, requestedBodyHeight + 8);
const bodyHeight = Math.min(requestedBodyHeight, viewBoxHeight - 8);
const bodyTop = (viewBoxHeight - bodyHeight) / 2;
const rightPortSpan = (rightPortCount - 1) * LMECHN1_PORT_ROW_SPACING;
const firstPortY = (viewBoxHeight - rightPortSpan) / 2;
const rightPortRows = Array.from(
{ length: rightPortCount },
(_, index) => firstPortY + index * LMECHN1_PORT_ROW_SPACING,
);
return {
bodyHeight,
bodyTop,
rightPortCount,
rightPortRows,
viewBoxHeight,
} as const;
}
export function AmesimLmechn1Symbol({
parameters,
surface,
}: ComponentSymbolRendererProps) {
// 组件库始终展示一个固定、易辨识的标准图;工作区才按实际端口数展开。
const metrics = lmechn1SymbolMetrics(
surface === "palette"
? { ...parameters, v1: LMECHN1_PALETTE_RIGHT_PORT_COUNT }
: parameters,
);
const centerY = metrics.viewBoxHeight / 2;
return (
{metrics.rightPortRows.map((y, index) => (
))}
linear
node
(displ.)
);
}
function Pnrp17ArrowPair({ centerY }: { centerY: number }) {
return (
);
}
export function AmesimPnrp17Symbol() {
return (
);
}