import { TextOnPath } from './text.mjs' import { getProps } from './utils.mjs' import { round, formatMm } from 'shared/utils.mjs' import { RawSpan } from 'shared/components/raw-span.mjs' export const pointCoords = (point) => point ? `[ ${round(point.x, 2)}, ${round(point.y, 2)} ]` : null export const Tr = ({ children }) => {children} export const KeyTd = ({ children }) => {children}: export const ValTd = ({ children }) => {children} export const TextAlongPath = ({ id, size, txt }) => ( {txt} ) export const PointCircle = ({ point, size, className = 'stroke-neutral-content' }) => ( ) const CpCircle = ({ point, className = 'fill-lining no-stroke' }) => ( ) const EpCircle = ({ point, className = 'fill-note no-stroke' }) => ( ) const pathDimensions = (from, to, cp1 = false, cp2 = false, path = false) => { const topLeft = { x: to.x < from.x ? to.x : from.x, y: to.y < from.y ? to.y : from.y, } const bottomRight = { x: to.x > from.x ? to.x : from.x, y: to.y > from.y ? to.y : from.y, } let bbox = false // Deal with curves if (cp1 && cp2) { if (cp1.x < topLeft.x) topLeft.x = cp1.x if (cp2.x < topLeft.x) topLeft.x = cp2.x if (cp1.x > bottomRight.x) bottomRight.x = cp1.x if (cp2.x > bottomRight.x) bottomRight.x = cp2.x if (cp1.y < topLeft.y) topLeft.y = cp1.y if (cp2.y < topLeft.y) topLeft.y = cp2.y if (cp1.y > bottomRight.y) bottomRight.y = cp1.y if (cp2.y > bottomRight.y) bottomRight.y = cp2.y // This undocumented core methods returns the curve's bounding box bbox = path.bbox() } const w = bottomRight.x - topLeft.x const h = bottomRight.y - topLeft.y const size = w > h ? w : h return { topLeft, bottomRight, w, h, size, bbox, } } export const Defs = () => ( ) export const svgProps = { xmlns: 'http://www.w3.org/2000/svg', xmlnsSvg: 'http://www.w3.org/2000/svg', xmlnsXlink: 'http://www.w3.org/1999/xlink', style: { maxHeight: 'inherit', strokeLinecap: 'round', strokeLinejoin: 'round' }, } const Line = (props) => { const ops = props.path.ops const from = ops[0].to const to = ops[1].to const { topLeft, bottomRight, w, h, size } = pathDimensions(from, to) const id = `${props.partName}_${props.pathName}_${props.i}` const xyProps = { className: 'stroke-neutral-content', strokeOpacity: '0.5', fill: 'none', strokeWidth: size / 300, } return ( ) } const Curve = (props) => { const ops = props.path.ops const from = ops[0].to const { to, cp1, cp2 } = ops[1] const { topLeft, w, h, size, bbox } = pathDimensions(from, to, cp1, cp2, props.path) const id = `${props.partName}_${props.pathName}_${props.i}` const cpProps = { className: 'stroke-success', strokeOpacity: '0.85', fill: 'none', strokeWidth: size / 300, } const xyProps = { ...cpProps, strokeOpacity: '0.5', className: 'stroke-neutral-content', markerEnd: 'url(#arrowTo)', markerStart: 'url(#arrowFrom)', } return ( ) } const MiniPath = (props) => { const bbox = props.path.bbox() const id = `${props.partName}_${props.pathName}_mini}` const w = bbox.bottomRight.x - bbox.topLeft.x const h = bbox.bottomRight.y - bbox.topLeft.y const size = w > h ? w : h const xyProps = { fill: 'none', strokeWidth: size / 300, strokeOpacity: '0.5', className: 'stroke-neutral-content', markerEnd: 'url(#arrowTo)', markerStart: 'url(#arrowFrom)', } return ( ) ) } const lineInfo = (props) => (
Line info
From{pointCoords(props.path.ops[0].to)}To{pointCoords(props.path.ops[1].to)}Length{formatMm(props.path.length(), props.gist.units, 'notags')}Width Height Part{props.partName}Draw Op {props.i}/{props.ops.length}
) const XrayLine = (props) => ( <> { evt.stopPropagation() props.showInfo(lineInfo(props)) }} /> ) const curveInfo = (props) => (
Curve info
From{pointCoords(props.path.ops[0].to)}Cp1{pointCoords(props.path.ops[1].cp1)}Cp2{pointCoords(props.path.ops[1].cp2)}To{pointCoords(props.path.ops[1].to)}Length Width Height Part{props.partName}Draw Op {props.i}/{props.ops.length}
) export const Attributes = ({ list }) => list ? (
    {Object.keys(list).map((key) => (
  • {key}: {list[key]}
  • ))}
) : null export const pathInfo = (props) => { const bbox = props.path.bbox() return (
Path info
Name{props.pathName}Length Width Height Top Left{pointCoords(bbox.topLeft)}Bottom Right{pointCoords(bbox.bottomRight)}Part{props.partName}Attributes
{props.path.ops.map((op, i) => ( {i} ))}
) } const PathOp = ({ op }) => { if (op.type === 'move') return ( Move to {pointCoords(op.to)} ) else if (op.type === 'line') return ( Line to {pointCoords(op.to)} ) else if (op.type === 'curve') return ( Curve to {pointCoords(op.to)}
Cp1: {pointCoords(op.cp1)}
Cp2: {pointCoords(op.cp2)}
) else if (op.type === 'noop') return NOOP else if (op.type === 'close') return Close else return FIXME: unknown path operation type: {op.type} } const XrayCurve = (props) => { const from = props.path.ops[0].to const { cp1, cp2, to } = props.path.ops[1] return ( <> { evt.stopPropagation() props.showInfo(curveInfo(props)) }} /> ) } const XrayPath = (props) => { const classes = props.path.attributes.get('class') if (typeof classes === 'string' && classes.includes('noxray')) return null const ops = props.path.divide() return ( { evt.preventDefault() props.showInfo(pathInfo(props)) }} markerStart="none" markerEnd="none" /> {ops.length > 0 ? ops.map((op, i) => op.ops[1].type === 'curve' ? ( ) : ( ) ) : null} ) } export const Path = (props) => { const { path, partName, pathName } = props if (path.hidden) return null const output = [] const pathId = 'path-' + partName + '-' + pathName let d = '' try { d = path.asPathstring() } catch (err) { // Bail out console.log(`Failed to generate pathstring for path ${pathId} in part ${partName}`, err) return null } output.push() if (path.attributes.get('data-text')) output.push() if (props.gist._state?.xray?.enabled) output.push() return output }