Skip to content

Commit 2ec4dbe

Browse files
kubeclaude
andcommitted
FE-43: Rename PolarToCartesian to Refraction and absorb feDisplacementMap
The Refraction component is now a self-contained effect: polar-to-cartesian conversion + displacement map application. This prepares FilterShell for composing multiple effects (specular rim, gloss, diffuse) that each consume the shared polar map independently. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 873a3fc commit 2ec4dbe

2 files changed

Lines changed: 33 additions & 22 deletions

File tree

libs/@hashintel/refractive/src/components/filter-shell.tsx

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Parts } from "../helpers/split-imagedata-to-parts";
22
import { buildCompositeSvgUrl } from "./composite/image";
33
import { CompositeParts } from "./composite/parts";
4-
import { PolarToCartesian } from "./polar-to-cartesian";
4+
import { Refraction } from "./refraction";
55

66
export type CompositeMode = "image" | "parts";
77

@@ -30,10 +30,11 @@ type FilterShellProps = {
3030

3131
/**
3232
* @private
33-
* Full SVG filter pipeline: blur → polar map compositing → polar-to-cartesian → displacement.
33+
* Full SVG filter pipeline: blur → polar map compositing → refraction effect.
3434
*
3535
* The `compositing` prop controls how the 9-patch polar map is assembled
36-
* inside the SVG filter graph.
36+
* inside the SVG filter graph. The polar map is then consumed by the
37+
* Refraction effect (and in the future, other effects like specular).
3738
*/
3839
export const FilterShell: React.FC<FilterShellProps> = ({
3940
id,
@@ -74,34 +75,28 @@ export const FilterShell: React.FC<FilterShellProps> = ({
7475
hideLeft,
7576
hideRight,
7677
)}
77-
result="polar_map"
7878
preserveAspectRatio="none"
79+
result="polar_map"
7980
/>
8081
) : (
8182
<CompositeParts
8283
parts={parts}
8384
elementRef={elementRef!}
8485
cornerWidth={cornerWidth}
85-
result="polar_map"
8686
hideTop={hideTop}
8787
hideBottom={hideBottom}
8888
hideLeft={hideLeft}
8989
hideRight={hideRight}
90+
result="polar_map"
9091
/>
9192
)}
9293

93-
<PolarToCartesian
94+
<Refraction
9495
magnitudeTable={magnitudeTable}
95-
in="polar_map"
96-
result="displacement_map"
97-
/>
98-
99-
<feDisplacementMap
100-
in="blurred_source"
101-
in2="displacement_map"
10296
scale={scale}
103-
xChannelSelector="R"
104-
yChannelSelector="G"
97+
in="polar_map"
98+
source="blurred_source"
99+
result="refracted"
105100
/>
106101
</filter>
107102
</defs>

libs/@hashintel/refractive/src/components/polar-to-cartesian.tsx renamed to libs/@hashintel/refractive/src/components/refraction.tsx

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,38 @@ const sinTable = generateTableValues(256, (i) => {
1111
return (Math.sin(angle) + 1) / 2;
1212
});
1313

14-
type PolarToCartesianProps = {
14+
type RefractionProps = {
1515
/** Magnitude lookup table (from generateMagnitudeTable). */
1616
magnitudeTable: string;
17+
/** Displacement scale factor. */
18+
scale: number;
1719
/** Input result name containing the polar map (R=ratio, G=angle). */
1820
in: string;
19-
/** Output result name for the cartesian displacement map. */
21+
/** Input result name for the source to be displaced. */
22+
source: string;
23+
/** Output result name for the displaced image. */
2024
result: string;
2125
};
2226

2327
/**
2428
* @private
25-
* SVG filter primitives that convert a polar distance map (R = border distance
26-
* ratio, G = displacement angle) into a cartesian displacement map (R = dx,
27-
* G = dy, centered at 0.5).
29+
* Refraction effect: converts a polar distance map into a cartesian displacement
30+
* field and applies it to a source image via feDisplacementMap.
2831
*
2932
* Pipeline:
3033
* 1. Extract angle (G) → apply cos/sin lookup tables via feComponentTransfer
31-
* 2. Extract distance ratio (R) → apply magnitude lookup table
34+
* 2. Extract distance ratio (R) → apply magnitude lookup table (Snell's law)
3235
* 3. Signed multiplication via feComposite arithmetic: magnitude × trig
36+
* 4. Apply displacement to source
3337
*
3438
* The signed multiplication formula `result = 2·A·B − A − B + 1` correctly
3539
* multiplies two values encoded in [0,1] centered at 0.5.
3640
*/
37-
export const PolarToCartesian: React.FC<PolarToCartesianProps> = ({
41+
export const Refraction: React.FC<RefractionProps> = ({
3842
magnitudeTable,
43+
scale,
3944
in: inResult,
45+
source,
4046
result,
4147
}) => (
4248
<>
@@ -77,6 +83,16 @@ export const PolarToCartesian: React.FC<PolarToCartesianProps> = ({
7783
k2={-1}
7884
k3={-1}
7985
k4={1}
86+
result={`${result}_displacement`}
87+
/>
88+
89+
{/* Apply displacement to source */}
90+
<feDisplacementMap
91+
in={source}
92+
in2={`${result}_displacement`}
93+
scale={scale}
94+
xChannelSelector="R"
95+
yChannelSelector="G"
8096
result={result}
8197
/>
8298
</>

0 commit comments

Comments
 (0)