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 ( ); }