263 lines
7.0 KiB
TypeScript
263 lines
7.0 KiB
TypeScript
import {
|
|
SYMBOL_ACCENT,
|
|
SYMBOL_FILL,
|
|
SYMBOL_MUTED,
|
|
SYMBOL_STROKE,
|
|
SymbolSvg,
|
|
} from "./primitives";
|
|
|
|
const PNEUMATIC_STROKE_WIDTH = 1.7;
|
|
const PNVO001_STROKE = "#8b134f";
|
|
const ORIFICE_CONTENT_SCALE = 0.6;
|
|
const ORIFICE_CONTENT_CENTER = { x: 32, y: 24 } as const;
|
|
const ORIFICE_CONTENT_TRANSFORM = `translate(${ORIFICE_CONTENT_CENTER.x} ${ORIFICE_CONTENT_CENTER.y}) scale(${ORIFICE_CONTENT_SCALE}) translate(${-ORIFICE_CONTENT_CENTER.x} ${-ORIFICE_CONTENT_CENTER.y})`;
|
|
|
|
function scaledOrificePoint(x: number, y: number) {
|
|
return {
|
|
x:
|
|
ORIFICE_CONTENT_CENTER.x +
|
|
(x - ORIFICE_CONTENT_CENTER.x) * ORIFICE_CONTENT_SCALE,
|
|
y:
|
|
ORIFICE_CONTENT_CENTER.y +
|
|
(y - ORIFICE_CONTENT_CENTER.y) * ORIFICE_CONTENT_SCALE,
|
|
};
|
|
}
|
|
|
|
export const PNVO001_PORT_ANCHORS = {
|
|
physicalLeft: scaledOrificePoint(0, 24),
|
|
physicalRight: scaledOrificePoint(64, 24),
|
|
signal: scaledOrificePoint(24.25, 56),
|
|
} as const;
|
|
|
|
type OrificeControl = "none" | "fixed" | "signal";
|
|
|
|
function Pnvo001Body({ control }: { control: OrificeControl }) {
|
|
return (
|
|
<g
|
|
data-orifice-control={control}
|
|
data-orifice-family="pnvo001"
|
|
transform={ORIFICE_CONTENT_TRANSFORM}
|
|
>
|
|
<path
|
|
d="M0 24H64"
|
|
data-orifice-part="flow-path"
|
|
stroke={PNVO001_STROKE}
|
|
strokeLinecap="butt"
|
|
strokeWidth="1.5"
|
|
/>
|
|
<path
|
|
d="M14.4 11Q31.7 27.5 48.7 11M14.4 38Q31.7 18.2 48.7 38"
|
|
data-orifice-part="curves"
|
|
stroke={PNVO001_STROKE}
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth="2.5"
|
|
/>
|
|
{control === "none" ? null : (
|
|
<>
|
|
<path
|
|
d="M16.5 54.5 42 3.5"
|
|
data-orifice-part="opening-arrow"
|
|
stroke={PNVO001_STROKE}
|
|
strokeLinecap="butt"
|
|
strokeWidth="1.5"
|
|
/>
|
|
<path
|
|
d="M48 -8 45.8 7.9 37 2.4Z"
|
|
data-orifice-part="opening-arrow-head"
|
|
fill={PNVO001_STROKE}
|
|
/>
|
|
</>
|
|
)}
|
|
{control === "signal" ? (
|
|
<path
|
|
d="M24.25 56V39L32 54.5"
|
|
data-orifice-part="signal-control"
|
|
stroke={PNVO001_STROKE}
|
|
strokeLinecap="butt"
|
|
strokeLinejoin="round"
|
|
strokeWidth="1.5"
|
|
/>
|
|
) : null}
|
|
</g>
|
|
);
|
|
}
|
|
|
|
/** 定系数气动孔口(AMESim PNOR001)。 */
|
|
export function AmesimPnor001Symbol() {
|
|
return (
|
|
<SymbolSvg className="component-symbol-amesim-pnor001-svg" domain="pneumatic">
|
|
<Pnvo001Body control="none" />
|
|
</SymbolSvg>
|
|
);
|
|
}
|
|
|
|
/** PNVO001 convenience variant whose opening is fixed by a parameter. */
|
|
export function AmesimPnvo001FixedSymbol() {
|
|
return (
|
|
<SymbolSvg
|
|
className="component-symbol-amesim-pnvo001-fixed-svg"
|
|
domain="pneumatic"
|
|
>
|
|
<Pnvo001Body control="fixed" />
|
|
</SymbolSvg>
|
|
);
|
|
}
|
|
|
|
/** Signal-modulated pneumatic orifice (AMESim PNVO001 / pn_morifice). */
|
|
export function AmesimPnvo001SignalSymbol() {
|
|
return (
|
|
<SymbolSvg
|
|
className="component-symbol-amesim-pnvo001-signal-svg"
|
|
domain="pneumatic"
|
|
>
|
|
<Pnvo001Body control="signal" />
|
|
</SymbolSvg>
|
|
);
|
|
}
|
|
|
|
type PipeSection = "C" | "R";
|
|
|
|
function PipeNetworkBody({ sections }: { sections: readonly PipeSection[] }) {
|
|
const left = 9;
|
|
const right = 55;
|
|
const top = 13;
|
|
const bottom = 35;
|
|
const sectionWidth = (right - left) / sections.length;
|
|
|
|
return (
|
|
<>
|
|
<path
|
|
d="M2 24h7M55 24h7"
|
|
stroke={SYMBOL_STROKE}
|
|
strokeLinecap="round"
|
|
strokeWidth={PNEUMATIC_STROKE_WIDTH}
|
|
/>
|
|
<rect
|
|
fill={SYMBOL_FILL}
|
|
height={bottom - top}
|
|
rx="2"
|
|
stroke={SYMBOL_STROKE}
|
|
strokeWidth={PNEUMATIC_STROKE_WIDTH}
|
|
width={right - left}
|
|
x={left}
|
|
y={top}
|
|
/>
|
|
{sections.slice(1).map((_, index) => {
|
|
const x = left + sectionWidth * (index + 1);
|
|
return (
|
|
<path
|
|
d={`M${x} ${top + 2}v${bottom - top - 4}`}
|
|
key={x}
|
|
stroke={SYMBOL_MUTED}
|
|
strokeWidth="1.1"
|
|
/>
|
|
);
|
|
})}
|
|
{sections.map((section, index) => (
|
|
<text
|
|
dominantBaseline="central"
|
|
fill={section === "R" ? SYMBOL_ACCENT : SYMBOL_MUTED}
|
|
fontFamily="Arial, sans-serif"
|
|
fontSize="9"
|
|
fontWeight="700"
|
|
key={`${section}-${index}`}
|
|
textAnchor="middle"
|
|
x={left + sectionWidth * (index + 0.5)}
|
|
y="24"
|
|
>
|
|
{section}
|
|
</text>
|
|
))}
|
|
</>
|
|
);
|
|
}
|
|
|
|
/** Pure pneumatic resistance line (AMESim PNL00R). */
|
|
export function AmesimPnl00rSymbol() {
|
|
return (
|
|
<SymbolSvg className="component-symbol-amesim-pnl00r-svg" domain="pneumatic">
|
|
<PipeNetworkBody sections={["R"]} />
|
|
</SymbolSvg>
|
|
);
|
|
}
|
|
|
|
/** C-R dynamic pneumatic line (AMESim PNL0001). */
|
|
export function AmesimPnl0001Symbol() {
|
|
return (
|
|
<SymbolSvg className="component-symbol-amesim-pnl0001-svg" domain="pneumatic">
|
|
<PipeNetworkBody sections={["C", "R"]} />
|
|
</SymbolSvg>
|
|
);
|
|
}
|
|
|
|
/** R-C-R dynamic pneumatic line (AMESim PNL0002). */
|
|
export function AmesimPnl0002Symbol() {
|
|
return (
|
|
<SymbolSvg className="component-symbol-amesim-pnl0002-svg" domain="pneumatic">
|
|
<PipeNetworkBody sections={["R", "C", "R"]} />
|
|
</SymbolSvg>
|
|
);
|
|
}
|
|
|
|
/** C-R-C dynamic pneumatic line (AMESim PNL0003). */
|
|
export function AmesimPnl0003Symbol() {
|
|
return (
|
|
<SymbolSvg className="component-symbol-amesim-pnl0003-svg" domain="pneumatic">
|
|
<PipeNetworkBody sections={["C", "R", "C"]} />
|
|
</SymbolSvg>
|
|
);
|
|
}
|
|
|
|
function JunctionTerminal({ x, y }: { x: number; y: number }) {
|
|
return (
|
|
<circle
|
|
cx={x}
|
|
cy={y}
|
|
fill={SYMBOL_FILL}
|
|
r="2"
|
|
stroke={SYMBOL_STROKE}
|
|
strokeWidth="1.3"
|
|
/>
|
|
);
|
|
}
|
|
|
|
/** Three-port pneumatic junction with one inlet-side and two outlet-side ports. */
|
|
export function AmesimPn3Node2Symbol() {
|
|
return (
|
|
<SymbolSvg className="component-symbol-amesim-pn3node2-svg" domain="pneumatic">
|
|
<path
|
|
d="M4 24h25M29 24C41 24 42 12 60 12M29 24c12 0 13 12 31 12"
|
|
stroke={SYMBOL_STROKE}
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={PNEUMATIC_STROKE_WIDTH}
|
|
/>
|
|
<circle cx="29" cy="24" fill={SYMBOL_ACCENT} r="3" />
|
|
<JunctionTerminal x={3} y={24} />
|
|
<JunctionTerminal x={61} y={12} />
|
|
<JunctionTerminal x={61} y={36} />
|
|
</SymbolSvg>
|
|
);
|
|
}
|
|
|
|
/** Four-port pneumatic junction with one inlet-side and three outlet-side ports. */
|
|
export function AmesimP4Node2Symbol() {
|
|
return (
|
|
<SymbolSvg className="component-symbol-amesim-p4node2-svg" domain="pneumatic">
|
|
<path
|
|
d="M4 24h24M28 24C40 24 42 8 60 8M28 24h32M28 24c12 0 14 16 32 16"
|
|
stroke={SYMBOL_STROKE}
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={PNEUMATIC_STROKE_WIDTH}
|
|
/>
|
|
<circle cx="28" cy="24" fill={SYMBOL_ACCENT} r="3" />
|
|
<JunctionTerminal x={3} y={24} />
|
|
<JunctionTerminal x={61} y={8} />
|
|
<JunctionTerminal x={61} y={24} />
|
|
<JunctionTerminal x={61} y={40} />
|
|
</SymbolSvg>
|
|
);
|
|
}
|