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
Atul Varma 2021-03-28 07:24:16 -04:00 zatwierdzone przez GitHub
rodzic 6fa6e0ba8a
commit 131c1f31cb
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
3 zmienionych plików z 74 dodań i 48 usunięć

Wyświetl plik

@ -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;

Wyświetl plik

@ -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 = {

Wyświetl plik

@ -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;
}