Orient mandala symbols around their anchor point. (#60)
This orients the mandala symbols around their anchor point, rather than the center of their bounding box (#24).pull/63/head
rodzic
6fa6e0ba8a
commit
131c1f31cb
|
@ -3,9 +3,10 @@ import { BBox, Point } from "../vendor/bezier-js";
|
|||
import { getAttachmentTransforms } from "./attach";
|
||||
import { getBoundingBoxCenter, uniformlyScaleToFit } from "./bounding-box";
|
||||
import { scalePointXY, subtractPoints } from "./point";
|
||||
import { AttachmentPointType, PointWithNormal } from "./specs";
|
||||
import { AttachmentPointType } from "./specs";
|
||||
import {
|
||||
createSvgSymbolContext,
|
||||
safeGetAttachmentPoint,
|
||||
SvgSymbolContent,
|
||||
SvgSymbolContext,
|
||||
SvgSymbolData,
|
||||
|
@ -21,47 +22,6 @@ import {
|
|||
|
||||
const DEFAULT_ATTACHMENT_SCALE = 0.5;
|
||||
|
||||
function getAttachmentPoint(
|
||||
s: SvgSymbolData,
|
||||
type: AttachmentPointType,
|
||||
idx: number = 0
|
||||
): PointWithNormal {
|
||||
const { specs } = s;
|
||||
if (!specs) {
|
||||
throw new AttachmentPointError(`Symbol ${s.name} has no specs.`);
|
||||
}
|
||||
const points = specs[type];
|
||||
if (!(points && points.length > idx)) {
|
||||
throw new AttachmentPointError(
|
||||
`Expected symbol ${s.name} to have at least ${
|
||||
idx + 1
|
||||
} ${type} attachment point(s).`
|
||||
);
|
||||
}
|
||||
|
||||
return points[idx];
|
||||
}
|
||||
|
||||
class AttachmentPointError extends Error {}
|
||||
|
||||
function safeGetAttachmentPoint(
|
||||
s: SvgSymbolData,
|
||||
type: AttachmentPointType,
|
||||
idx: number = 0
|
||||
): PointWithNormal | null {
|
||||
try {
|
||||
return getAttachmentPoint(s, type, idx);
|
||||
} catch (e) {
|
||||
if (e instanceof AttachmentPointError) {
|
||||
console.log(e.message);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export type CreatureContextType = SvgSymbolContext & {
|
||||
attachmentScale: number;
|
||||
parent: SvgSymbolData | null;
|
||||
|
|
|
@ -6,9 +6,9 @@ import { DEFAULT_BG_COLOR } from "../colors";
|
|||
import { ExportSvgButton } from "../export-svg";
|
||||
import { HoverDebugHelper } from "../hover-debug-helper";
|
||||
import { NumericSlider } from "../numeric-slider";
|
||||
import { reversePoint } from "../point";
|
||||
import {
|
||||
createSvgSymbolContext,
|
||||
safeGetAttachmentPoint,
|
||||
SvgSymbolContent,
|
||||
SvgSymbolContext,
|
||||
SvgSymbolData,
|
||||
|
@ -24,8 +24,25 @@ import { SvgVocabulary } from "../svg-vocabulary";
|
|||
import { SymbolContextWidget } from "../symbol-context-widget";
|
||||
import { NumericRange, range } from "../util";
|
||||
import { Random } from "../random";
|
||||
import { PointWithNormal } from "../specs";
|
||||
import { getAttachmentTransforms } from "../attach";
|
||||
|
||||
const EYE = SvgVocabulary.get("eye");
|
||||
const EYE = SvgVocabulary.get("eye_vertical");
|
||||
|
||||
/**
|
||||
* Returns the anchor point of the given symbol; if it doesn't have
|
||||
* an anchor point, return a reasonable default one by taking the
|
||||
* center of the symbol and having the normal point along the positive
|
||||
* x-axis.
|
||||
*/
|
||||
function getAnchorOrCenter(symbol: SvgSymbolData): PointWithNormal {
|
||||
return (
|
||||
safeGetAttachmentPoint(symbol, "anchor") || {
|
||||
point: getBoundingBoxCenter(symbol.bbox),
|
||||
normal: { x: 1, y: 0 },
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const MandalaCircle: React.FC<
|
||||
{
|
||||
|
@ -34,13 +51,21 @@ const MandalaCircle: React.FC<
|
|||
numSymbols: number;
|
||||
} & SvgSymbolContext
|
||||
> = (props) => {
|
||||
const center = getBoundingBoxCenter(props.data.bbox);
|
||||
const degreesPerItem = 360 / props.numSymbols;
|
||||
const { translation, rotation } = getAttachmentTransforms(
|
||||
{
|
||||
point: { x: 0, y: 0 },
|
||||
normal: { x: 1, y: 0 },
|
||||
},
|
||||
getAnchorOrCenter(props.data)
|
||||
);
|
||||
|
||||
const symbol = (
|
||||
<SvgTransform
|
||||
transform={[
|
||||
svgTranslate({ x: props.radius, y: 0 }),
|
||||
svgTranslate(reversePoint(center)),
|
||||
svgRotate(rotation),
|
||||
svgTranslate(translation),
|
||||
]}
|
||||
>
|
||||
<SvgSymbolContent {...props} />
|
||||
|
@ -64,7 +89,7 @@ const RADIUS: NumericParams = {
|
|||
min: 0,
|
||||
max: 1000,
|
||||
step: 1,
|
||||
default: 400,
|
||||
default: 50,
|
||||
};
|
||||
|
||||
const NUM_SYMBOLS: NumericParams = {
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from "react";
|
|||
import { SVGProps } from "react";
|
||||
import { BBox } from "../vendor/bezier-js";
|
||||
import { FILL_REPLACEMENT_COLOR, STROKE_REPLACEMENT_COLOR } from "./colors";
|
||||
import { Specs } from "./specs";
|
||||
import { AttachmentPointType, PointWithNormal, Specs } from "./specs";
|
||||
import type { SvgSymbolMetadata } from "./svg-symbol-metadata";
|
||||
import { VisibleSpecs } from "./visible-specs";
|
||||
|
||||
|
@ -114,3 +114,44 @@ export const SvgSymbolContent: React.FC<
|
|||
</g>
|
||||
);
|
||||
};
|
||||
|
||||
export class AttachmentPointError extends Error {}
|
||||
|
||||
export function getAttachmentPoint(
|
||||
s: SvgSymbolData,
|
||||
type: AttachmentPointType,
|
||||
idx: number = 0
|
||||
): PointWithNormal {
|
||||
const { specs } = s;
|
||||
if (!specs) {
|
||||
throw new AttachmentPointError(`Symbol ${s.name} has no specs.`);
|
||||
}
|
||||
const points = specs[type];
|
||||
if (!(points && points.length > idx)) {
|
||||
throw new AttachmentPointError(
|
||||
`Expected symbol ${s.name} to have at least ${
|
||||
idx + 1
|
||||
} ${type} attachment point(s).`
|
||||
);
|
||||
}
|
||||
|
||||
return points[idx];
|
||||
}
|
||||
|
||||
export function safeGetAttachmentPoint(
|
||||
s: SvgSymbolData,
|
||||
type: AttachmentPointType,
|
||||
idx: number = 0
|
||||
): PointWithNormal | null {
|
||||
try {
|
||||
return getAttachmentPoint(s, type, idx);
|
||||
} catch (e) {
|
||||
if (e instanceof AttachmentPointError) {
|
||||
console.log(e.message);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue