Make attachment point code more DRY.
rodzic
2384d1eac3
commit
11c27b905f
|
@ -1,10 +1,16 @@
|
||||||
|
import type { AttachmentPointType } from "./specs";
|
||||||
|
|
||||||
export const STROKE_REPLACEMENT_COLOR = "#000000";
|
export const STROKE_REPLACEMENT_COLOR = "#000000";
|
||||||
export const FILL_REPLACEMENT_COLOR = "#ffffff";
|
export const FILL_REPLACEMENT_COLOR = "#ffffff";
|
||||||
|
|
||||||
export const TAIL_ATTACHMENT_COLOR = "#ff0000";
|
export const ATTACHMENT_POINT_COLORS: {
|
||||||
export const LEG_ATTACHMENT_COLOR = "#ffff00";
|
[key in AttachmentPointType]: string;
|
||||||
export const ARM_ATTACHMENT_COLOR = "#00ff00";
|
} = {
|
||||||
export const HORN_ATTACHMENT_COLOR = "#00ffff";
|
tail: "#ff0000",
|
||||||
export const CROWN_ATTACHMENT_COLOR = "#0000ff";
|
leg: "#ffff00",
|
||||||
|
arm: "#00ff00",
|
||||||
|
horn: "#00ffff",
|
||||||
|
crown: "#0000ff",
|
||||||
|
};
|
||||||
|
|
||||||
export const NESTING_BOUNDING_BOX_COLOR = "#ff00ff";
|
export const NESTING_BOUNDING_BOX_COLOR = "#ff00ff";
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { BBox } from "../../vendor/bezier-js";
|
||||||
import { dilateBoundingBox, getBoundingBoxSize } from "../bounding-box";
|
import { dilateBoundingBox, getBoundingBoxSize } from "../bounding-box";
|
||||||
import { FILL_REPLACEMENT_COLOR, STROKE_REPLACEMENT_COLOR } from "../colors";
|
import { FILL_REPLACEMENT_COLOR, STROKE_REPLACEMENT_COLOR } from "../colors";
|
||||||
import * as colors from "../colors";
|
import * as colors from "../colors";
|
||||||
import { PointWithNormal, Specs } from "../specs";
|
import { iterAttachmentPoints, AttachmentPoint, Specs } from "../specs";
|
||||||
|
|
||||||
import type { SvgSymbolData, SvgSymbolElement } from "../vocabulary";
|
import type { SvgSymbolData, SvgSymbolElement } from "../vocabulary";
|
||||||
import { SvgVocabulary } from "../svg-vocabulary";
|
import { SvgVocabulary } from "../svg-vocabulary";
|
||||||
|
@ -61,36 +61,28 @@ const ATTACHMENT_POINT_NORMAL_LENGTH = 50;
|
||||||
|
|
||||||
const ATTACHMENT_POINT_NORMAL_STROKE = 4;
|
const ATTACHMENT_POINT_NORMAL_STROKE = 4;
|
||||||
|
|
||||||
const AttachmentPoints: React.FC<{
|
const VisibleAttachmentPoint: React.FC<{
|
||||||
color: string;
|
point: AttachmentPoint;
|
||||||
points: PointWithNormal[];
|
}> = ({ point: ap }) => {
|
||||||
}> = (props) => (
|
const { x, y } = ap.point;
|
||||||
<>
|
const x2 = x + ap.normal.x * ATTACHMENT_POINT_NORMAL_LENGTH;
|
||||||
{props.points.map((pwn, i) => {
|
const y2 = y + ap.normal.y * ATTACHMENT_POINT_NORMAL_LENGTH;
|
||||||
const { x, y } = pwn.point;
|
const color = colors.ATTACHMENT_POINT_COLORS[ap.type];
|
||||||
const x2 = x + pwn.normal.x * ATTACHMENT_POINT_NORMAL_LENGTH;
|
|
||||||
const y2 = y + pwn.normal.y * ATTACHMENT_POINT_NORMAL_LENGTH;
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={i}>
|
<>
|
||||||
<circle
|
<circle fill={color} r={ATTACHMENT_POINT_RADIUS} cx={x} cy={y} />
|
||||||
fill={props.color}
|
|
||||||
r={ATTACHMENT_POINT_RADIUS}
|
|
||||||
cx={x}
|
|
||||||
cy={y}
|
|
||||||
/>
|
|
||||||
<line
|
<line
|
||||||
x1={x}
|
x1={x}
|
||||||
y1={y}
|
y1={y}
|
||||||
x2={x2}
|
x2={x2}
|
||||||
y2={y2}
|
y2={y2}
|
||||||
stroke={props.color}
|
stroke={color}
|
||||||
strokeWidth={ATTACHMENT_POINT_NORMAL_STROKE}
|
strokeWidth={ATTACHMENT_POINT_NORMAL_STROKE}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const BoundingBoxes: React.FC<{ fill: string; bboxes: BBox[] }> = (props) => (
|
const BoundingBoxes: React.FC<{ fill: string; bboxes: BBox[] }> = (props) => (
|
||||||
<>
|
<>
|
||||||
|
@ -113,36 +105,9 @@ const BoundingBoxes: React.FC<{ fill: string; bboxes: BBox[] }> = (props) => (
|
||||||
const SvgSymbolSpecs: React.FC<{ specs: Specs }> = ({ specs }) => {
|
const SvgSymbolSpecs: React.FC<{ specs: Specs }> = ({ specs }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{specs.tail && (
|
{Array.from(iterAttachmentPoints(specs)).map((point, i) => (
|
||||||
<AttachmentPoints
|
<VisibleAttachmentPoint key={i} point={point} />
|
||||||
color={colors.TAIL_ATTACHMENT_COLOR}
|
))}
|
||||||
points={specs.tail}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{specs.leg && (
|
|
||||||
<AttachmentPoints
|
|
||||||
color={colors.LEG_ATTACHMENT_COLOR}
|
|
||||||
points={specs.leg}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{specs.arm && (
|
|
||||||
<AttachmentPoints
|
|
||||||
color={colors.ARM_ATTACHMENT_COLOR}
|
|
||||||
points={specs.arm}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{specs.horn && (
|
|
||||||
<AttachmentPoints
|
|
||||||
color={colors.HORN_ATTACHMENT_COLOR}
|
|
||||||
points={specs.horn}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{specs.crown && (
|
|
||||||
<AttachmentPoints
|
|
||||||
color={colors.CROWN_ATTACHMENT_COLOR}
|
|
||||||
points={specs.crown}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{specs.nesting && (
|
{specs.nesting && (
|
||||||
<BoundingBoxes
|
<BoundingBoxes
|
||||||
fill={colors.NESTING_BOUNDING_BOX_COLOR}
|
fill={colors.NESTING_BOUNDING_BOX_COLOR}
|
||||||
|
|
83
lib/specs.ts
83
lib/specs.ts
|
@ -11,14 +11,45 @@ export type PointWithNormal = {
|
||||||
normal: Point;
|
normal: Point;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Specs = {
|
type AttachmentPointSpecs = {
|
||||||
tail?: PointWithNormal[];
|
tail: PointWithNormal[];
|
||||||
leg?: PointWithNormal[];
|
leg: PointWithNormal[];
|
||||||
arm?: PointWithNormal[];
|
arm: PointWithNormal[];
|
||||||
horn?: PointWithNormal[];
|
horn: PointWithNormal[];
|
||||||
crown?: PointWithNormal[];
|
crown: PointWithNormal[];
|
||||||
nesting?: BBox[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type FullSpecs = AttachmentPointSpecs & {
|
||||||
|
nesting: BBox[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Specs = Partial<FullSpecs>;
|
||||||
|
|
||||||
|
export type AttachmentPointType = keyof AttachmentPointSpecs;
|
||||||
|
|
||||||
|
export type AttachmentPoint = PointWithNormal & {
|
||||||
|
type: AttachmentPointType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ATTACHMENT_POINT_TYPES: AttachmentPointType[] = [
|
||||||
|
"tail",
|
||||||
|
"leg",
|
||||||
|
"arm",
|
||||||
|
"horn",
|
||||||
|
"crown",
|
||||||
|
];
|
||||||
|
|
||||||
|
export function* iterAttachmentPoints(specs: Specs): Iterable<AttachmentPoint> {
|
||||||
|
for (let type of ATTACHMENT_POINT_TYPES) {
|
||||||
|
const points = specs[type];
|
||||||
|
if (points) {
|
||||||
|
for (let point of points) {
|
||||||
|
yield { ...point, type };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const NUM_ARROW_POINTS = 4;
|
const NUM_ARROW_POINTS = 4;
|
||||||
const ARROW_TOP_POINT_IDX = 0;
|
const ARROW_TOP_POINT_IDX = 0;
|
||||||
const ARROW_BOTTOM_POINT_IDX = 2;
|
const ARROW_BOTTOM_POINT_IDX = 2;
|
||||||
|
@ -76,34 +107,24 @@ function concat<T>(first: T[] | undefined, second: T[]): T[] {
|
||||||
return first ? [...first, ...second] : second;
|
return first ? [...first, ...second] : second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ATTACHMENT_COLOR_MAP = new Map(
|
||||||
|
ATTACHMENT_POINT_TYPES.map((type) => [
|
||||||
|
colors.ATTACHMENT_POINT_COLORS[type],
|
||||||
|
type,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
function updateSpecs(fill: string, path: string, specs: Specs): Specs {
|
function updateSpecs(fill: string, path: string, specs: Specs): Specs {
|
||||||
switch (fill) {
|
const attachmentType = ATTACHMENT_COLOR_MAP.get(fill);
|
||||||
case colors.TAIL_ATTACHMENT_COLOR:
|
|
||||||
|
if (attachmentType) {
|
||||||
return {
|
return {
|
||||||
...specs,
|
...specs,
|
||||||
tail: concat(specs.tail, getArrowPoints(path)),
|
[attachmentType]: concat(specs[attachmentType], getArrowPoints(path)),
|
||||||
};
|
};
|
||||||
case colors.LEG_ATTACHMENT_COLOR:
|
}
|
||||||
return {
|
|
||||||
...specs,
|
if (fill === colors.NESTING_BOUNDING_BOX_COLOR) {
|
||||||
leg: concat(specs.leg, getArrowPoints(path)),
|
|
||||||
};
|
|
||||||
case colors.ARM_ATTACHMENT_COLOR:
|
|
||||||
return {
|
|
||||||
...specs,
|
|
||||||
arm: concat(specs.arm, getArrowPoints(path)),
|
|
||||||
};
|
|
||||||
case colors.HORN_ATTACHMENT_COLOR:
|
|
||||||
return {
|
|
||||||
...specs,
|
|
||||||
horn: concat(specs.horn, getArrowPoints(path)),
|
|
||||||
};
|
|
||||||
case colors.CROWN_ATTACHMENT_COLOR:
|
|
||||||
return {
|
|
||||||
...specs,
|
|
||||||
crown: concat(specs.crown, getArrowPoints(path)),
|
|
||||||
};
|
|
||||||
case colors.NESTING_BOUNDING_BOX_COLOR:
|
|
||||||
return {
|
return {
|
||||||
...specs,
|
...specs,
|
||||||
nesting: concat(specs.nesting, getBoundingBoxes(path)),
|
nesting: concat(specs.nesting, getBoundingBoxes(path)),
|
||||||
|
|
|
@ -27,5 +27,8 @@
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
"typescript": "^4.1.3"
|
"typescript": "^4.1.3"
|
||||||
}
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"since 2017-06"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue