%% tikzlibrarytikzphysics.surface.code.tex
%% -----------------------------------------------------------
%% Surface module for tikzphysics.
%% Provides shapes for contact geometry used in mechanics problems:
%%   - physicsplatformleft, physicsplatformright, physicsplatformboth
%%   - physicswedge
%% and the user-facing styles physicsplatform-left/right/both and physicswedge.
%%
%% Internal namespace : \tikzphysics@surface@...
%% Requires           : tikz, patterns, calc, tikzphysics.core
%%
%% Design notes:
%%
%%  * All shapes use a single "dims bundle" \savedmacro that runs
%%    \tikzphysics@surface@set<shape>dims ONCE at node-declaration and caches
%%    all derived dimensions together.  Anchors unpack the bundle
%%    with one macro call and then read per-dim values directly.
%%    No anchor re-reads pgfkeys at access time.
%%
%%  * Precedence for physicswedge geometry (width w, height h, angle a):
%%       1. user set `physics wedge angle`  -> a wins, h derived from w,a
%%       2. user set `physics wedge height` (no angle) -> h wins, a derived
%%       3. neither                  -> mode-specific default angle
%%    See \tikzphysics@surface@setwedgedims below.
%%
%%  * `physics wedge right angle at' is a pgfkeys `.is choice' key.  No
%%    \ifx cascades on strings.
%%
%%  * For all three right-angle-at modes, the apex x-offset is
%%    stored in \tikzphysics@surface@tx.  Anchors use a single formula
%%    regardless of mode (e.g. centroid = (tx/3, -hy/3) always).
%%
%% Author  : Vaibhav Blayer
%% Version : v1.2.0 (2026-09-05)
%% License : LPPL 1.3c
%% -----------------------------------------------------------

\usetikzlibrary{patterns, calc}
\usetikzlibrary{tikzphysics.core}

\makeatletter

\tikzphysics@declarehook{platform}
\tikzphysics@declarehook{wedge}
\tikzphysics@declarehook{ground}
\tikzphysics@declarehook{ceiling}
\tikzphysics@declarehook{wall-left}
\tikzphysics@declarehook{wall-right}

%% ============================================================
%%  INTERNAL DIMENSIONS AND STATE
%% ============================================================

\newdimen\tikzphysics@surface@dx    %% full width
\newdimen\tikzphysics@surface@dy    %% full height
\newdimen\tikzphysics@surface@hx    %% half width
\newdimen\tikzphysics@surface@hy    %% half height
\newdimen\tikzphysics@surface@tx    %% apex x-offset from node centre (all modes)
\newdimen\tikzphysics@surface@sw    %% platform strip width

%% Angled wall corners (used by physicsplatformleft/right/both).
%% A = outer-near, B = inner-near, C = inner-far, D = outer-far
%% where "near" means near the platform corner and "far" means at the
%% free end of the wall.  In the default orientation (wall angle
%% = -90 deg, wall pointing straight down), wA/wB sit on y=+hy and
%% wC/wD on y=-hy. The wall's outer-near corner stays coincident with
%% the end of the floor surface, making the contact line continuous.
\newdimen\tikzphysics@surface@wAx  \newdimen\tikzphysics@surface@wAy
\newdimen\tikzphysics@surface@wBx  \newdimen\tikzphysics@surface@wBy
\newdimen\tikzphysics@surface@wCx  \newdimen\tikzphysics@surface@wCy
\newdimen\tikzphysics@surface@wDx  \newdimen\tikzphysics@surface@wDy
%% Second wall (physicsplatformboth's right wall)
\newdimen\tikzphysics@surface@rwAx \newdimen\tikzphysics@surface@rwAy
\newdimen\tikzphysics@surface@rwBx \newdimen\tikzphysics@surface@rwBy
\newdimen\tikzphysics@surface@rwCx \newdimen\tikzphysics@surface@rwCy
\newdimen\tikzphysics@surface@rwDx \newdimen\tikzphysics@surface@rwDy

\def\tikzphysics@surface@wedgeangle{45}
\def\tikzphysics@surface@wedgeraq{br}
\def\tikzphysics@surface@angleflag{0}     %% 1 iff user set `physics wedge angle'
\def\tikzphysics@surface@heightflag{0}    %% 1 iff user set `physics wedge height'
\def\tikzphysics@surface@ang{45}          %% working angle (degrees)

\def\tikzphysics@surface@stripwidth{0.25cm}   %% default 0.25cm

%% Wall-angle state.  Shared between physicsplatformleft/right (they
%% use \tikzphysics@surface@wallangle); physicsplatformboth additionally reads
%% \tikzphysics@surface@leftwallangle and \tikzphysics@surface@rightwallangle.
%% Default -90 degrees = wall points straight down. Angle is measured
%% from +x axis, CCW positive, and
%% describes the direction the wall extends from the platform corner.
\def\tikzphysics@surface@wallangle{-90}
\def\tikzphysics@surface@leftwallangle{-90}
\def\tikzphysics@surface@rightwallangle{-90}

%% ---- mode-specific default angles (used when neither angle nor
%%                                    explicit height is given) ----
\def\tikzphysics@surface@defaultangle@bl {30}
\def\tikzphysics@surface@defaultangle@br {30}
\def\tikzphysics@surface@defaultangle@top{45}

%% ============================================================
%%  GEOMETRY HELPERS
%% ============================================================

%% dims for a rectangular platform: just hx, hy, sw
\newcommand{\tikzphysics@surface@setplatformdims}{%
  \pgfmathsetlength{\tikzphysics@surface@dx}{\pgfkeysvalueof{/pgf/minimum width}}%
  \pgfmathsetlength{\tikzphysics@surface@dy}{\pgfkeysvalueof{/pgf/minimum height}}%
  \tikzphysics@surface@hx=.5\tikzphysics@surface@dx
  \tikzphysics@surface@hy=.5\tikzphysics@surface@dy
  \tikzphysics@resolve@length{\tikzphysics@surface@sw}{\tikzphysics@surface@stripwidth}%
  \ifdim\tikzphysics@surface@sw<\tikzphysics@surface@dx\relax\else
    \PackageError{tikzphysics}{strip width must be smaller than platform width}%
      {Reduce strip width or increase platform width.}%
  \fi
  \ifdim\tikzphysics@surface@sw<\tikzphysics@surface@dy\relax\else
    \PackageError{tikzphysics}{strip width must be smaller than platform depth}%
      {Reduce strip width or increase platform depth.}%
  \fi
}

%% dims for a flat strip shape (physicsground, physicsceiling, physicswall*): hx, hy.
%% No strip-within-strip, so no `sw' here.
\newcommand{\tikzphysics@surface@setflatdims}{%
  \pgfmathsetlength{\tikzphysics@surface@dx}{\pgfkeysvalueof{/pgf/minimum width}}%
  \pgfmathsetlength{\tikzphysics@surface@dy}{\pgfkeysvalueof{/pgf/minimum height}}%
  \tikzphysics@surface@hx=.5\tikzphysics@surface@dx
  \tikzphysics@surface@hy=.5\tikzphysics@surface@dy
}

%% ============================================================
%%  WALL GEOMETRY HELPER
%%
%%  Computes a wall strip of thickness sw and length 2*hy. Its outer-near
%%  corner is the corresponding endpoint of the floor's contact surface.
%%  The inner-near point B is the exact intersection of the wall's inner
%%  edge and the floor's inner edge. This miter makes the complete platform
%%  one sharply bent polygon, rather than separately joined components.
%%
%%  Corner labels:
%%    A = outer-near,  B = inner-near,
%%    C = inner-far,   D = outer-far.
%%    IC = fixed platform corner (retained as an internal storage name).
%%
%%  Depends on \tikzphysics@surface@hx, @hy, @sw being set.
%% ============================================================

%% Fixed platform-corner dimensions. The IC names are retained internally to
%% keep the saved-dimension plumbing compact.
\newdimen\tikzphysics@surface@ICx  \newdimen\tikzphysics@surface@ICy
%% Second IC for physicsplatformboth's right wall
\newdimen\tikzphysics@surface@rICx \newdimen\tikzphysics@surface@rICy

\newcommand{\tikzphysics@surface@setwall}[2]{%
  \csname tikzphysics@surface@setwall@#1\endcsname{#2}%
}

\def\tikzphysics@surface@setwall@left#1{%
  \pgfmathsetmacro{\tikzphysics@surface@@c}{cos(#1)}%
  \pgfmathsetmacro{\tikzphysics@surface@@s}{sin(#1)}%
  %% A is the fixed floor-top-left corner. The inward normal is
  %% n=(-sin(theta),cos(theta)).
  \tikzphysics@surface@ICx=-\tikzphysics@surface@hx
  \tikzphysics@surface@ICy= \tikzphysics@surface@hy
  \tikzphysics@surface@wAx=\tikzphysics@surface@ICx
  \tikzphysics@surface@wAy=\tikzphysics@surface@ICy
  %% Intersect the offset wall edge with y=hy-sw. At 180 degrees the
  %% result is the straight continuation. A 0-degree left wall folds back
  %% over the floor and has no finite miter.
  \pgfmathsetmacro{\tikzphysics@surface@@abss}{abs(\tikzphysics@surface@@s)}%
  \ifdim\tikzphysics@surface@@abss pt<0.0001pt\relax
    \ifdim\tikzphysics@surface@@c pt<0pt\relax
      \tikzphysics@surface@wBx=\tikzphysics@surface@wAx
    \else
      \PackageError{tikzphysics}{wall angle cannot fold a left wall back over the floor}%
        {Use an angle other than 0 degrees modulo 360.}%
      \tikzphysics@surface@wBx=\tikzphysics@surface@wAx
    \fi
  \else
    \pgfmathsetlength{\tikzphysics@surface@wBx}%
      {\tikzphysics@surface@wAx-\tikzphysics@surface@sw*(1+\tikzphysics@surface@@c)/\tikzphysics@surface@@s}%
  \fi
  \tikzphysics@surface@wBy=\dimexpr\tikzphysics@surface@hy-\tikzphysics@surface@sw\relax
  \pgfmathsetlength{\tikzphysics@surface@wDx}{\tikzphysics@surface@wAx+2*\tikzphysics@surface@hy*\tikzphysics@surface@@c}%
  \pgfmathsetlength{\tikzphysics@surface@wDy}{\tikzphysics@surface@wAy+2*\tikzphysics@surface@hy*\tikzphysics@surface@@s}%
  \pgfmathsetlength{\tikzphysics@surface@wCx}{\tikzphysics@surface@wDx-\tikzphysics@surface@sw*\tikzphysics@surface@@s}%
  \pgfmathsetlength{\tikzphysics@surface@wCy}{\tikzphysics@surface@wDy+\tikzphysics@surface@sw*\tikzphysics@surface@@c}%
}

\def\tikzphysics@surface@setwall@right#1{%
  \pgfmathsetmacro{\tikzphysics@surface@@c}{cos(#1)}%
  \pgfmathsetmacro{\tikzphysics@surface@@s}{sin(#1)}%
  %% A is the fixed floor-top-right corner. The inward normal is
  %% n=(sin(theta),-cos(theta)).
  \tikzphysics@surface@ICx=\tikzphysics@surface@hx
  \tikzphysics@surface@ICy=\tikzphysics@surface@hy
  \tikzphysics@surface@wAx=\tikzphysics@surface@ICx
  \tikzphysics@surface@wAy=\tikzphysics@surface@ICy
  %% Mirror of the left-wall miter. A 0-degree right wall is a straight
  %% continuation; a 180-degree right wall is the non-finite folded case.
  \pgfmathsetmacro{\tikzphysics@surface@@abss}{abs(\tikzphysics@surface@@s)}%
  \ifdim\tikzphysics@surface@@abss pt<0.0001pt\relax
    \ifdim\tikzphysics@surface@@c pt>0pt\relax
      \tikzphysics@surface@wBx=\tikzphysics@surface@wAx
    \else
      \PackageError{tikzphysics}{wall angle cannot fold a right wall back over the floor}%
        {Use an angle other than 180 degrees modulo 360.}%
      \tikzphysics@surface@wBx=\tikzphysics@surface@wAx
    \fi
  \else
    \pgfmathsetlength{\tikzphysics@surface@wBx}%
      {\tikzphysics@surface@wAx+\tikzphysics@surface@sw*(1-\tikzphysics@surface@@c)/\tikzphysics@surface@@s}%
  \fi
  \tikzphysics@surface@wBy=\dimexpr\tikzphysics@surface@hy-\tikzphysics@surface@sw\relax
  \pgfmathsetlength{\tikzphysics@surface@wDx}{\tikzphysics@surface@wAx+2*\tikzphysics@surface@hy*\tikzphysics@surface@@c}%
  \pgfmathsetlength{\tikzphysics@surface@wDy}{\tikzphysics@surface@wAy+2*\tikzphysics@surface@hy*\tikzphysics@surface@@s}%
  \pgfmathsetlength{\tikzphysics@surface@wCx}{\tikzphysics@surface@wDx+\tikzphysics@surface@sw*\tikzphysics@surface@@s}%
  \pgfmathsetlength{\tikzphysics@surface@wCy}{\tikzphysics@surface@wDy-\tikzphysics@surface@sw*\tikzphysics@surface@@c}%
}

%% Combined setdims for physicsplatformleft: floor dims + angled wall.
\newcommand{\tikzphysics@surface@setpldims}{%
  \tikzphysics@surface@setplatformdims
  \tikzphysics@surface@setwall{left}{\tikzphysics@surface@wallangle}%
}

%% Combined setdims for physicsplatformright: floor dims + angled wall.
\newcommand{\tikzphysics@surface@setprdims}{%
  \tikzphysics@surface@setplatformdims
  \tikzphysics@surface@setwall{right}{\tikzphysics@surface@wallangle}%
}

%% physicsplatformboth: two walls.  Left wall IC goes into ICx/ICy,
%% right wall IC goes into rICx/rICy.
\newcommand{\tikzphysics@surface@setpbdims}{%
  \tikzphysics@surface@setplatformdims
  %% Left wall
  \tikzphysics@surface@setwall{left}{\tikzphysics@surface@leftwallangle}%
  %% snapshot left wall corners
  \tikzphysics@surface@rwAx=\tikzphysics@surface@wAx \tikzphysics@surface@rwAy=\tikzphysics@surface@wAy
  \tikzphysics@surface@rwBx=\tikzphysics@surface@wBx \tikzphysics@surface@rwBy=\tikzphysics@surface@wBy
  \tikzphysics@surface@rwCx=\tikzphysics@surface@wCx \tikzphysics@surface@rwCy=\tikzphysics@surface@wCy
  \tikzphysics@surface@rwDx=\tikzphysics@surface@wDx \tikzphysics@surface@rwDy=\tikzphysics@surface@wDy
  %% snapshot left IC
  \tikzphysics@surface@rICx=\tikzphysics@surface@ICx \tikzphysics@surface@rICy=\tikzphysics@surface@ICy
  %% Right wall
  \tikzphysics@surface@setwall{right}{\tikzphysics@surface@rightwallangle}%
  %% Now swap: wA-wD hold RIGHT wall, rwA-rwD hold LEFT wall.
  %% We want wA-wD = LEFT, rwA-rwD = RIGHT.
  \@tempdima=\tikzphysics@surface@wAx \tikzphysics@surface@wAx=\tikzphysics@surface@rwAx \tikzphysics@surface@rwAx=\@tempdima
  \@tempdima=\tikzphysics@surface@wAy \tikzphysics@surface@wAy=\tikzphysics@surface@rwAy \tikzphysics@surface@rwAy=\@tempdima
  \@tempdima=\tikzphysics@surface@wBx \tikzphysics@surface@wBx=\tikzphysics@surface@rwBx \tikzphysics@surface@rwBx=\@tempdima
  \@tempdima=\tikzphysics@surface@wBy \tikzphysics@surface@wBy=\tikzphysics@surface@rwBy \tikzphysics@surface@rwBy=\@tempdima
  \@tempdima=\tikzphysics@surface@wCx \tikzphysics@surface@wCx=\tikzphysics@surface@rwCx \tikzphysics@surface@rwCx=\@tempdima
  \@tempdima=\tikzphysics@surface@wCy \tikzphysics@surface@wCy=\tikzphysics@surface@rwCy \tikzphysics@surface@rwCy=\@tempdima
  \@tempdima=\tikzphysics@surface@wDx \tikzphysics@surface@wDx=\tikzphysics@surface@rwDx \tikzphysics@surface@rwDx=\@tempdima
  \@tempdima=\tikzphysics@surface@wDy \tikzphysics@surface@wDy=\tikzphysics@surface@rwDy \tikzphysics@surface@rwDy=\@tempdima
  %% Swap ICs: ICx/ICy = left IC, rICx/rICy = right IC
  \@tempdima=\tikzphysics@surface@ICx \tikzphysics@surface@ICx=\tikzphysics@surface@rICx \tikzphysics@surface@rICx=\@tempdima
  \@tempdima=\tikzphysics@surface@ICy \tikzphysics@surface@ICy=\tikzphysics@surface@rICy \tikzphysics@surface@rICy=\@tempdima
}

%% Given dx and ang, compute dy and tx for the current
%% right-angle-at mode.  Dispatch via \csname, no \ifx.
\newcommand{\tikzphysics@surface@computedyfromangle}{%
  \csname tikzphysics@surface@computedims@\tikzphysics@surface@wedgeraq\endcsname
}

\newcommand{\tikzphysics@surface@validatewedgeangle}{%
  \ifdim\tikzphysics@surface@ang pt>0pt\relax\else
    \PackageError{tikzphysics}{physics wedge angle must be greater than 0 degrees}%
      {Choose an angle strictly between 0 and 90 degrees.}%
  \fi
  \ifdim\tikzphysics@surface@ang pt<90pt\relax\else
    \PackageError{tikzphysics}{physics wedge angle must be less than 90 degrees}%
      {Choose an angle strictly between 0 and 90 degrees.}%
  \fi
}

\def\tikzphysics@surface@computedims@bl{%
  %% right angle at bl: apex directly above bl
  %%   legs = (bl,br) and (bl,apex);  apex = (-hx, +hy)
  \pgfmathsetlength{\tikzphysics@surface@dy}{\tikzphysics@surface@dx*tan(\tikzphysics@surface@ang)}%
  \tikzphysics@surface@tx=-.5\tikzphysics@surface@dx
}
\def\tikzphysics@surface@computedims@br{%
  %% right angle at br: apex directly above br; apex = (+hx, +hy)
  \pgfmathsetlength{\tikzphysics@surface@dy}{\tikzphysics@surface@dx*tan(\tikzphysics@surface@ang)}%
  \tikzphysics@surface@tx=.5\tikzphysics@surface@dx
}
\def\tikzphysics@surface@computedims@top{%
  %% right angle at apex: Thales geometry
  %%   dy = dx * sin(2a) / 2
  %%   tx = dx * cos(2a) / 2
  \pgfmathsetlength{\tikzphysics@surface@dy}{\tikzphysics@surface@dx*sin(2*\tikzphysics@surface@ang)/2}%
  \pgfmathsetlength{\tikzphysics@surface@tx}{\tikzphysics@surface@dx*cos(2*\tikzphysics@surface@ang)/2}%
}

%% Given dx and dy, compute ang and tx for the current mode.
\newcommand{\tikzphysics@surface@computeanglefromdy}{%
  \csname tikzphysics@surface@anglefromdy@\tikzphysics@surface@wedgeraq\endcsname
}

\def\tikzphysics@surface@anglefromdy@bl{%
  \pgfmathsetmacro{\tikzphysics@surface@ang}{atan(\tikzphysics@surface@dy/\tikzphysics@surface@dx)}%
  \tikzphysics@surface@tx=-.5\tikzphysics@surface@dx
}
\def\tikzphysics@surface@anglefromdy@br{%
  \pgfmathsetmacro{\tikzphysics@surface@ang}{atan(\tikzphysics@surface@dy/\tikzphysics@surface@dx)}%
  \tikzphysics@surface@tx=.5\tikzphysics@surface@dx
}
\def\tikzphysics@surface@anglefromdy@top{%
  %% Thales inverse:
  %%   ang = (1/2) * asin(2*dy/dx)    (requires 2*dy <= dx)
  %%   tx  = (1/2) * sqrt(dx^2 - 4*dy^2)
  \ifdim\tikzphysics@surface@dy>.5\tikzphysics@surface@dx\relax
    \PackageError{tikzphysics}%
      {physics wedge height > physics wedge width/2 is impossible with
       `physics wedge right angle at=top'}%
      {With right-angle-at=top the apex must lie on a semicircle
       (Thales' theorem). Reduce physics wedge height to at most
       physics wedge width/2, or drop `physics wedge right angle at=top'.}%
  \fi
  \pgfmathsetmacro{\tikzphysics@surface@ang}%
    {0.5*asin(2*\tikzphysics@surface@dy/\tikzphysics@surface@dx)}%
  \pgfmathsetlength{\tikzphysics@surface@tx}%
    {0.5*sqrt(\tikzphysics@surface@dx*\tikzphysics@surface@dx
              - 4*\tikzphysics@surface@dy*\tikzphysics@surface@dy)}%
}

%% The only place pgfkeys are read for wedge geometry.
%% Resolves all dimensions according to the precedence rule
%% angle > height > mode-default, then saves them to dx/dy/hx/hy/tx.
\newcommand{\tikzphysics@surface@setwedgedims}{%
  \pgfmathsetlength{\tikzphysics@surface@dx}{\pgfkeysvalueof{/pgf/minimum width}}%
  \ifnum\tikzphysics@surface@angleflag=1
    %% case 1: angle authoritative
    \pgfmathsetmacro{\tikzphysics@surface@ang}{\tikzphysics@surface@wedgeangle}%
    \tikzphysics@surface@validatewedgeangle
    \tikzphysics@surface@computedyfromangle
  \else
    \ifnum\tikzphysics@surface@heightflag=1
      %% case 2: height authoritative
      \pgfmathsetlength{\tikzphysics@surface@dy}%
        {\pgfkeysvalueof{/pgf/minimum height}}%
      \tikzphysics@surface@computeanglefromdy
    \else
      %% case 3: mode-specific default angle
      \edef\tikzphysics@surface@ang{%
        \csname tikzphysics@surface@defaultangle@\tikzphysics@surface@wedgeraq\endcsname}%
      \tikzphysics@surface@validatewedgeangle
      \tikzphysics@surface@computedyfromangle
    \fi
  \fi
  \tikzphysics@surface@hx=.5\tikzphysics@surface@dx
  \tikzphysics@surface@hy=.5\tikzphysics@surface@dy
}

%% ============================================================
%%  TIKZ KEYS  (scoped, unit-aware)
%% ============================================================

\tikzset{
  %% ---- platform sizing ----
  physics platform width/.code  = {\tikzphysics@length@keyhandler{/pgf/minimum width}{#1}},
  physics platform depth/.code  = {\tikzphysics@length@keyhandler{/pgf/minimum height}{#1}},
  physics strip width/.code     = {\def\tikzphysics@surface@stripwidth{#1}},
  platform width/.style = {physics platform width={#1}},
  platform depth/.style = {physics platform depth={#1}},
  strip width/.style    = {physics strip width={#1}},
  %% ---- wall direction (physicsplatform-left/right/both) ----
  %% Angle from +x axis, CCW positive, of the direction the wall
  %% extends from the platform corner. Default -90 deg = straight down.
  physics wall angle/.code = {%
    \def\tikzphysics@surface@wallangle{#1}%
    \def\tikzphysics@surface@leftwallangle{#1}%
    \def\tikzphysics@surface@rightwallangle{#1}%
  },
  %% physicsplatform-both supports independent left/right wall angles.
  physics left wall angle/.code  = {\def\tikzphysics@surface@leftwallangle{#1}},
  physics right wall angle/.code = {\def\tikzphysics@surface@rightwallangle{#1}},
  %% Concise public forms; retain the prefixed keys as collision-safe aliases.
  wall angle/.style       = {physics wall angle={#1}},
  left wall angle/.style  = {physics left wall angle={#1}},
  right wall angle/.style = {physics right wall angle={#1}},
  %% ---- wedge sizing ----
  physics wedge width/.code     = {\tikzphysics@length@keyhandler{/pgf/minimum width}{#1}},
  physics wedge height/.code    = {%
    \tikzphysics@length@keyhandler{/pgf/minimum height}{#1}%
    \def\tikzphysics@surface@heightflag{1}%
  },
  %% ---- wedge shape controls ----
  physics wedge angle/.code       = {%
    \def\tikzphysics@surface@wedgeangle{#1}%
    \def\tikzphysics@surface@angleflag{1}%
  },
  physics wedge right angle at/.is choice,
  physics wedge right angle at/bl/.code  = {\def\tikzphysics@surface@wedgeraq{bl}},
  physics wedge right angle at/br/.code  = {\def\tikzphysics@surface@wedgeraq{br}},
  physics wedge right angle at/top/.code = {\def\tikzphysics@surface@wedgeraq{top}},
  %% Concise public forms; the physics-prefixed keys remain available when
  %% generic key names would collide with another TikZ library.
  wedge width/.style          = {physics wedge width={#1}},
  wedge height/.style         = {physics wedge height={#1}},
  wedge angle/.style          = {physics wedge angle={#1}},
  wedge right angle at/.style = {physics wedge right angle at={#1}},
  %% ---- flat strip sizing (ground/ceiling/walls) ----
  physics ground width/.code    = {\tikzphysics@length@keyhandler{/pgf/minimum width}{#1}},
  physics ground depth/.code    = {\tikzphysics@length@keyhandler{/pgf/minimum height}{#1}},
  physics ceiling width/.code   = {\tikzphysics@length@keyhandler{/pgf/minimum width}{#1}},
  physics ceiling depth/.code   = {\tikzphysics@length@keyhandler{/pgf/minimum height}{#1}},
  physics wall thickness/.code  = {\tikzphysics@length@keyhandler{/pgf/minimum width}{#1}},
  physics wall height/.code     = {\tikzphysics@length@keyhandler{/pgf/minimum height}{#1}},
  ground width/.style      = {physics ground width={#1}},
  ground depth/.style      = {physics ground depth={#1}},
  ceiling width/.style     = {physics ceiling width={#1}},
  ceiling depth/.style     = {physics ceiling depth={#1}},
  wall thickness/.style    = {physics wall thickness={#1}},
  wall height/.style       = {physics wall height={#1}},
}

%% ============================================================
%%  PLATFORM SHAPES
%%
%%  Each platform uses individual \savedmacro's per dimension.
%%  This avoids pgf's internal re-edef of bundled \def's (which
%%  would try to expand not-yet-defined names).  The cost of
%%  calling setplatformdims 3x per node is negligible.
%% ============================================================

%% --------------------------------------------------------------
%%  physicsplatformleft
%%
%%  Geometry = one closed floor-and-wall polygon. Its outer boundary is
%%  the continuous contact line and its inner boundary uses an exact miter,
%%  so the bend is a sharp V rather than a rounded or patched connection.
%%
%%  Floor (fixed, horizontal strip along the top):
%%    x in [-hx, +hx],  y in [hy-sw, +hy]
%%  Wall (bends at the fixed platform corner):
%%    corner A = (-hx, hy)
%%    default (wall angle = -90): wall lies in
%%      x in [-hx, -hx+sw],  y in [-hy, +hy]
%%    user-facing key `wall angle' sets the wall direction from A.
%%
%%  Corner labels (intrinsic to the angled wall):
%%    A = outer-near, B = inner-near,
%%    C = inner-far,  D = outer-far
%%  where "near" is the platform-side short end and "far" is the free
%%  short end; "outer" faces away from the floor interior.
%% --------------------------------------------------------------
\pgfdeclareshape{physicsplatformleft}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchorborder[from=rectangle]

  %% Floor dims
  \savedmacro{\tikzphysics@surface@pl@hx}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@hx{\the\tikzphysics@surface@hx}%
  }
  \savedmacro{\tikzphysics@surface@pl@hy}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@hy{\the\tikzphysics@surface@hy}%
  }
  \savedmacro{\tikzphysics@surface@pl@sw}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@sw{\the\tikzphysics@surface@sw}%
  }
  %% Angled wall corners
  \savedmacro{\tikzphysics@surface@pl@wAx}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@wAx{\the\tikzphysics@surface@wAx}%
  }
  \savedmacro{\tikzphysics@surface@pl@wAy}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@wAy{\the\tikzphysics@surface@wAy}%
  }
  \savedmacro{\tikzphysics@surface@pl@wBx}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@wBx{\the\tikzphysics@surface@wBx}%
  }
  \savedmacro{\tikzphysics@surface@pl@wBy}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@wBy{\the\tikzphysics@surface@wBy}%
  }
  \savedmacro{\tikzphysics@surface@pl@wCx}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@wCx{\the\tikzphysics@surface@wCx}%
  }
  \savedmacro{\tikzphysics@surface@pl@wCy}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@wCy{\the\tikzphysics@surface@wCy}%
  }
  \savedmacro{\tikzphysics@surface@pl@wDx}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@wDx{\the\tikzphysics@surface@wDx}%
  }
  \savedmacro{\tikzphysics@surface@pl@wDy}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@wDy{\the\tikzphysics@surface@wDy}%
  }
  %% Fixed platform corner
  \savedmacro{\tikzphysics@surface@pl@ICx}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@ICx{\the\tikzphysics@surface@ICx}%
  }
  \savedmacro{\tikzphysics@surface@pl@ICy}{%
    \tikzphysics@surface@setpldims
    \edef\tikzphysics@surface@pl@ICy{\the\tikzphysics@surface@ICy}%
  }

  %% One closed, mitered polygon. The pattern is evaluated once over the
  %% complete floor-and-wall geometry.
  \backgroundpath{%
    \pgfpathmoveto{\pgfpoint{\tikzphysics@surface@pl@wDx}{\tikzphysics@surface@pl@wDy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pl@wAx}{\tikzphysics@surface@pl@wAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pl@hx}
                            {\dimexpr\tikzphysics@surface@pl@hy-\tikzphysics@surface@pl@sw\relax}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pl@wBx}{\tikzphysics@surface@pl@wBy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pl@wCx}{\tikzphysics@surface@pl@wCy}}%
    \pgfpathclose
  }
  %% One continuous contact line: wall free end -> corner -> floor end.
  \foregroundpath{%
    \pgfsetlinewidth{0.5pt}%
    \pgfpathmoveto{\pgfpoint{\tikzphysics@surface@pl@wDx}{\tikzphysics@surface@pl@wDy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pl@wAx}{\tikzphysics@surface@pl@wAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}}%
    \pgfusepath{stroke}%
  }

  %% ---- fixed corner where the wall surface meets the floor surface ----
  \anchor{corner}{\pgf@x=\tikzphysics@surface@pl@ICx \pgf@y=\tikzphysics@surface@pl@ICy}

  %% ---- floor corners (fixed, ignore wall angle) ----
  \anchor{floor-tl}{\pgf@x=-\tikzphysics@surface@pl@hx \pgf@y=\tikzphysics@surface@pl@hy}
  \anchor{floor-tr}{\pgf@x= \tikzphysics@surface@pl@hx \pgf@y=\tikzphysics@surface@pl@hy}
  \anchor{floor-br}{\pgf@x= \tikzphysics@surface@pl@hx
                     \pgf@y=\dimexpr\tikzphysics@surface@pl@hy-\tikzphysics@surface@pl@sw\relax}
  \anchor{floor-bl}{\pgf@x=-\tikzphysics@surface@pl@hx
                     \pgf@y=\dimexpr\tikzphysics@surface@pl@hy-\tikzphysics@surface@pl@sw\relax}
  \anchor{floor-top-mid}   {\pgf@x=0pt \pgf@y=\tikzphysics@surface@pl@hy}
  \anchor{floor-bottom-mid}{\pgf@x=0pt
                     \pgf@y=\dimexpr\tikzphysics@surface@pl@hy-\tikzphysics@surface@pl@sw\relax}
  \anchor{floor-left-mid}  {\pgf@x=-\tikzphysics@surface@pl@hx
     \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pl@hy-0.5*\tikzphysics@surface@pl@sw}}
  \anchor{floor-right-mid} {\pgf@x= \tikzphysics@surface@pl@hx
     \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pl@hy-0.5*\tikzphysics@surface@pl@sw}}
  \anchor{floor-center}    {\pgf@x=0pt
     \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pl@hy-0.5*\tikzphysics@surface@pl@sw}}

  %% ---- wall corners ----
  \anchor{wall-A}{\pgf@x=\tikzphysics@surface@pl@wAx \pgf@y=\tikzphysics@surface@pl@wAy}
  \anchor{wall-B}{\pgf@x=\tikzphysics@surface@pl@wBx \pgf@y=\tikzphysics@surface@pl@wBy}
  \anchor{wall-C}{\pgf@x=\tikzphysics@surface@pl@wCx \pgf@y=\tikzphysics@surface@pl@wCy}
  \anchor{wall-D}{\pgf@x=\tikzphysics@surface@pl@wDx \pgf@y=\tikzphysics@surface@pl@wDy}

  %% ---- wall mids ----
  \anchor{wall-outer-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pl@wAx+\tikzphysics@surface@pl@wDx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pl@wAy+\tikzphysics@surface@pl@wDy)/2}}
  \anchor{wall-inner-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pl@wBx+\tikzphysics@surface@pl@wCx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pl@wBy+\tikzphysics@surface@pl@wCy)/2}}
  \anchor{wall-near-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pl@wAx+\tikzphysics@surface@pl@wBx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pl@wAy+\tikzphysics@surface@pl@wBy)/2}}
  \anchor{wall-far-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pl@wCx+\tikzphysics@surface@pl@wDx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pl@wCy+\tikzphysics@surface@pl@wDy)/2}}
  \anchor{wall-center}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pl@wAx+\tikzphysics@surface@pl@wBx
                              +\tikzphysics@surface@pl@wCx+\tikzphysics@surface@pl@wDx)/4}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pl@wAy+\tikzphysics@surface@pl@wBy
                              +\tikzphysics@surface@pl@wCy+\tikzphysics@surface@pl@wDy)/4}}

  %% ---- numeric edge anchors on the floor (CCW from FBL) ----
  %% floor-bottom : FBL -> FBR (left to right across the floor's
  %%                inner edge)
  %% floor-right  : FBR -> FTR (up the floor's right side)
  %% floor-top    : FTR -> FTL (right to left across the floor's
  %%                outer top -- the contact surface)
  %% floor-left   : FTL -> FBL (down the floor's left side)
  \tikzphysics@declareedgeanchors{floor-bottom}
    {-\tikzphysics@surface@pl@hx}{\dimexpr\tikzphysics@surface@pl@hy-\tikzphysics@surface@pl@sw\relax}
    {\tikzphysics@surface@pl@hx}{\dimexpr\tikzphysics@surface@pl@hy-\tikzphysics@surface@pl@sw\relax}
  \tikzphysics@declareedgeanchors{floor-right}
    {\tikzphysics@surface@pl@hx}{\dimexpr\tikzphysics@surface@pl@hy-\tikzphysics@surface@pl@sw\relax}
    {\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}
  \tikzphysics@declareedgeanchors{floor-top}
    {\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}
    {-\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}
  \tikzphysics@declareedgeanchors{floor-left}
    {-\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}
    {-\tikzphysics@surface@pl@hx}{\dimexpr\tikzphysics@surface@pl@hy-\tikzphysics@surface@pl@sw\relax}

  %% ---- numeric edge anchors on the wall ----
  %% Each edge parameterises 0 -> 100 in the natural direction
  %% along that face of the wall.  Direction is chosen so that
  %% 0 is on the outer-or-near side (closer to the corner for
  %% outer/inner; outer side for near/far).
  %%   wall-outer : wA  -> wD   (along outer long edge, near -> far)
  %%   wall-inner : wB  -> wC   (along inner long edge, near -> far)
  %%   wall-near  : wA  -> wB   (along near short edge, outer -> inner)
  %%   wall-far   : wD  -> wC   (along far short edge, outer -> inner)
  \tikzphysics@declareedgeanchors{wall-outer}
    {\tikzphysics@surface@pl@wAx}{\tikzphysics@surface@pl@wAy}
    {\tikzphysics@surface@pl@wDx}{\tikzphysics@surface@pl@wDy}
  \tikzphysics@declareedgeanchors{wall-inner}
    {\tikzphysics@surface@pl@wBx}{\tikzphysics@surface@pl@wBy}
    {\tikzphysics@surface@pl@wCx}{\tikzphysics@surface@pl@wCy}
  \tikzphysics@declareedgeanchors{wall-near}
    {\tikzphysics@surface@pl@wAx}{\tikzphysics@surface@pl@wAy}
    {\tikzphysics@surface@pl@wBx}{\tikzphysics@surface@pl@wBy}
  \tikzphysics@declareedgeanchors{wall-far}
    {\tikzphysics@surface@pl@wDx}{\tikzphysics@surface@pl@wDy}
    {\tikzphysics@surface@pl@wCx}{\tikzphysics@surface@pl@wCy}

}

%% --------------------------------------------------------------
%%  physicsplatformright
%%
%%  Mirror of physicsplatformleft: wall attaches on the right side of
%%  the floor strip. Corner at (+hx, hy). Default wall angle = -90
%%  degrees (wall extends straight down).
%% --------------------------------------------------------------
\pgfdeclareshape{physicsplatformright}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchorborder[from=rectangle]

  \savedmacro{\tikzphysics@surface@pr@hx}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@hx{\the\tikzphysics@surface@hx}%
  }
  \savedmacro{\tikzphysics@surface@pr@hy}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@hy{\the\tikzphysics@surface@hy}%
  }
  \savedmacro{\tikzphysics@surface@pr@sw}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@sw{\the\tikzphysics@surface@sw}%
  }
  \savedmacro{\tikzphysics@surface@pr@wAx}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@wAx{\the\tikzphysics@surface@wAx}%
  }
  \savedmacro{\tikzphysics@surface@pr@wAy}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@wAy{\the\tikzphysics@surface@wAy}%
  }
  \savedmacro{\tikzphysics@surface@pr@wBx}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@wBx{\the\tikzphysics@surface@wBx}%
  }
  \savedmacro{\tikzphysics@surface@pr@wBy}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@wBy{\the\tikzphysics@surface@wBy}%
  }
  \savedmacro{\tikzphysics@surface@pr@wCx}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@wCx{\the\tikzphysics@surface@wCx}%
  }
  \savedmacro{\tikzphysics@surface@pr@wCy}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@wCy{\the\tikzphysics@surface@wCy}%
  }
  \savedmacro{\tikzphysics@surface@pr@wDx}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@wDx{\the\tikzphysics@surface@wDx}%
  }
  \savedmacro{\tikzphysics@surface@pr@wDy}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@wDy{\the\tikzphysics@surface@wDy}%
  }
  \savedmacro{\tikzphysics@surface@pr@ICx}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@ICx{\the\tikzphysics@surface@ICx}%
  }
  \savedmacro{\tikzphysics@surface@pr@ICy}{%
    \tikzphysics@surface@setprdims
    \edef\tikzphysics@surface@pr@ICy{\the\tikzphysics@surface@ICy}%
  }

  %% One closed, sharply mitered floor-and-wall polygon.
  \backgroundpath{%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pr@wAx}{\tikzphysics@surface@pr@wAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pr@wDx}{\tikzphysics@surface@pr@wDy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pr@wCx}{\tikzphysics@surface@pr@wCy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pr@wBx}{\tikzphysics@surface@pr@wBy}}%
    \pgfpathlineto{\pgfpoint{-\tikzphysics@surface@pr@hx}
                            {\dimexpr\tikzphysics@surface@pr@hy-\tikzphysics@surface@pr@sw\relax}}%
    \pgfpathclose
  }
  %% One continuous contact line: floor end -> corner -> wall free end.
  \foregroundpath{%
    \pgfsetlinewidth{0.5pt}%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pr@wAx}{\tikzphysics@surface@pr@wAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pr@wDx}{\tikzphysics@surface@pr@wDy}}%
    \pgfusepath{stroke}%
  }

  %% ---- fixed corner where the floor and wall surfaces meet ----
  \anchor{corner}{\pgf@x=\tikzphysics@surface@pr@ICx \pgf@y=\tikzphysics@surface@pr@ICy}

  %% ---- floor corners (fixed) ----
  \anchor{floor-tl}{\pgf@x=-\tikzphysics@surface@pr@hx \pgf@y=\tikzphysics@surface@pr@hy}
  \anchor{floor-tr}{\pgf@x= \tikzphysics@surface@pr@hx \pgf@y=\tikzphysics@surface@pr@hy}
  \anchor{floor-br}{\pgf@x= \tikzphysics@surface@pr@hx
                     \pgf@y=\dimexpr\tikzphysics@surface@pr@hy-\tikzphysics@surface@pr@sw\relax}
  \anchor{floor-bl}{\pgf@x=-\tikzphysics@surface@pr@hx
                     \pgf@y=\dimexpr\tikzphysics@surface@pr@hy-\tikzphysics@surface@pr@sw\relax}
  \anchor{floor-top-mid}   {\pgf@x=0pt \pgf@y=\tikzphysics@surface@pr@hy}
  \anchor{floor-bottom-mid}{\pgf@x=0pt
                     \pgf@y=\dimexpr\tikzphysics@surface@pr@hy-\tikzphysics@surface@pr@sw\relax}
  \anchor{floor-left-mid}  {\pgf@x=-\tikzphysics@surface@pr@hx
     \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pr@hy-0.5*\tikzphysics@surface@pr@sw}}
  \anchor{floor-right-mid} {\pgf@x= \tikzphysics@surface@pr@hx
     \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pr@hy-0.5*\tikzphysics@surface@pr@sw}}
  \anchor{floor-center}    {\pgf@x=0pt
     \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pr@hy-0.5*\tikzphysics@surface@pr@sw}}

  %% ---- wall corners ----
  \anchor{wall-A}{\pgf@x=\tikzphysics@surface@pr@wAx \pgf@y=\tikzphysics@surface@pr@wAy}
  \anchor{wall-B}{\pgf@x=\tikzphysics@surface@pr@wBx \pgf@y=\tikzphysics@surface@pr@wBy}
  \anchor{wall-C}{\pgf@x=\tikzphysics@surface@pr@wCx \pgf@y=\tikzphysics@surface@pr@wCy}
  \anchor{wall-D}{\pgf@x=\tikzphysics@surface@pr@wDx \pgf@y=\tikzphysics@surface@pr@wDy}

  %% ---- wall mids ----
  \anchor{wall-outer-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pr@wAx+\tikzphysics@surface@pr@wDx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pr@wAy+\tikzphysics@surface@pr@wDy)/2}}
  \anchor{wall-inner-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pr@wBx+\tikzphysics@surface@pr@wCx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pr@wBy+\tikzphysics@surface@pr@wCy)/2}}
  \anchor{wall-near-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pr@wAx+\tikzphysics@surface@pr@wBx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pr@wAy+\tikzphysics@surface@pr@wBy)/2}}
  \anchor{wall-far-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pr@wCx+\tikzphysics@surface@pr@wDx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pr@wCy+\tikzphysics@surface@pr@wDy)/2}}
  \anchor{wall-center}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pr@wAx+\tikzphysics@surface@pr@wBx
                              +\tikzphysics@surface@pr@wCx+\tikzphysics@surface@pr@wDx)/4}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pr@wAy+\tikzphysics@surface@pr@wBy
                              +\tikzphysics@surface@pr@wCy+\tikzphysics@surface@pr@wDy)/4}}

  %% ---- numeric edge anchors on the floor (CCW from FBL) ----
  \tikzphysics@declareedgeanchors{floor-bottom}
    {-\tikzphysics@surface@pr@hx}{\dimexpr\tikzphysics@surface@pr@hy-\tikzphysics@surface@pr@sw\relax}
    {\tikzphysics@surface@pr@hx}{\dimexpr\tikzphysics@surface@pr@hy-\tikzphysics@surface@pr@sw\relax}
  \tikzphysics@declareedgeanchors{floor-right}
    {\tikzphysics@surface@pr@hx}{\dimexpr\tikzphysics@surface@pr@hy-\tikzphysics@surface@pr@sw\relax}
    {\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}
  \tikzphysics@declareedgeanchors{floor-top}
    {\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}
    {-\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}
  \tikzphysics@declareedgeanchors{floor-left}
    {-\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}
    {-\tikzphysics@surface@pr@hx}{\dimexpr\tikzphysics@surface@pr@hy-\tikzphysics@surface@pr@sw\relax}

  %% ---- numeric edge anchors on the wall ----
  %% Same intrinsic convention as physicsplatformleft:
  %%   wall-outer : wA -> wD   (along outer long edge, near -> far)
  %%   wall-inner : wB -> wC   (along inner long edge, near -> far)
  %%   wall-near  : wA -> wB   (along near short edge, outer -> inner)
  %%   wall-far   : wD -> wC   (along far short edge, outer -> inner)
  \tikzphysics@declareedgeanchors{wall-outer}
    {\tikzphysics@surface@pr@wAx}{\tikzphysics@surface@pr@wAy}
    {\tikzphysics@surface@pr@wDx}{\tikzphysics@surface@pr@wDy}
  \tikzphysics@declareedgeanchors{wall-inner}
    {\tikzphysics@surface@pr@wBx}{\tikzphysics@surface@pr@wBy}
    {\tikzphysics@surface@pr@wCx}{\tikzphysics@surface@pr@wCy}
  \tikzphysics@declareedgeanchors{wall-near}
    {\tikzphysics@surface@pr@wAx}{\tikzphysics@surface@pr@wAy}
    {\tikzphysics@surface@pr@wBx}{\tikzphysics@surface@pr@wBy}
  \tikzphysics@declareedgeanchors{wall-far}
    {\tikzphysics@surface@pr@wDx}{\tikzphysics@surface@pr@wDy}
    {\tikzphysics@surface@pr@wCx}{\tikzphysics@surface@pr@wCy}

}

%% --------------------------------------------------------------
%%  physicsplatformboth
%%
%%  One closed floor-and-two-wall polygon with two exact inner miters.
%%  User keys:
%%    wall angle         -- sets BOTH walls (convenience)
%%    left wall angle    -- just the left wall
%%    right wall angle   -- just the right wall
%%  Default for both walls is -90 degrees.
%%
%%  Left wall  corners -> lA, lB, lC, lD (stored in pb@lAx .. pb@lDy)
%%  Right wall corners -> rA, rB, rC, rD (stored in pb@rAx .. pb@rDy)
%%  Using the same A/B/C/D convention per wall as physicsplatformleft/right.
%% --------------------------------------------------------------
\pgfdeclareshape{physicsplatformboth}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchorborder[from=rectangle]

  \savedmacro{\tikzphysics@surface@pb@hx}{%
    \tikzphysics@surface@setpbdims
    \edef\tikzphysics@surface@pb@hx{\the\tikzphysics@surface@hx}%
  }
  \savedmacro{\tikzphysics@surface@pb@hy}{%
    \tikzphysics@surface@setpbdims
    \edef\tikzphysics@surface@pb@hy{\the\tikzphysics@surface@hy}%
  }
  \savedmacro{\tikzphysics@surface@pb@sw}{%
    \tikzphysics@surface@setpbdims
    \edef\tikzphysics@surface@pb@sw{\the\tikzphysics@surface@sw}%
  }
  %% Left wall corners (wA/B/C/D from setpbdims)
  \savedmacro{\tikzphysics@surface@pb@lAx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lAx{\the\tikzphysics@surface@wAx}}
  \savedmacro{\tikzphysics@surface@pb@lAy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lAy{\the\tikzphysics@surface@wAy}}
  \savedmacro{\tikzphysics@surface@pb@lBx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lBx{\the\tikzphysics@surface@wBx}}
  \savedmacro{\tikzphysics@surface@pb@lBy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lBy{\the\tikzphysics@surface@wBy}}
  \savedmacro{\tikzphysics@surface@pb@lCx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lCx{\the\tikzphysics@surface@wCx}}
  \savedmacro{\tikzphysics@surface@pb@lCy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lCy{\the\tikzphysics@surface@wCy}}
  \savedmacro{\tikzphysics@surface@pb@lDx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lDx{\the\tikzphysics@surface@wDx}}
  \savedmacro{\tikzphysics@surface@pb@lDy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lDy{\the\tikzphysics@surface@wDy}}
  %% Right wall corners (rwA/B/C/D from setpbdims)
  \savedmacro{\tikzphysics@surface@pb@rAx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rAx{\the\tikzphysics@surface@rwAx}}
  \savedmacro{\tikzphysics@surface@pb@rAy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rAy{\the\tikzphysics@surface@rwAy}}
  \savedmacro{\tikzphysics@surface@pb@rBx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rBx{\the\tikzphysics@surface@rwBx}}
  \savedmacro{\tikzphysics@surface@pb@rBy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rBy{\the\tikzphysics@surface@rwBy}}
  \savedmacro{\tikzphysics@surface@pb@rCx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rCx{\the\tikzphysics@surface@rwCx}}
  \savedmacro{\tikzphysics@surface@pb@rCy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rCy{\the\tikzphysics@surface@rwCy}}
  \savedmacro{\tikzphysics@surface@pb@rDx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rDx{\the\tikzphysics@surface@rwDx}}
  \savedmacro{\tikzphysics@surface@pb@rDy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rDy{\the\tikzphysics@surface@rwDy}}
  %% Left wall IC
  \savedmacro{\tikzphysics@surface@pb@lICx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lICx{\the\tikzphysics@surface@ICx}}
  \savedmacro{\tikzphysics@surface@pb@lICy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@lICy{\the\tikzphysics@surface@ICy}}
  %% Right wall IC
  \savedmacro{\tikzphysics@surface@pb@rICx}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rICx{\the\tikzphysics@surface@rICx}}
  \savedmacro{\tikzphysics@surface@pb@rICy}{%
    \tikzphysics@surface@setpbdims \edef\tikzphysics@surface@pb@rICy{\the\tikzphysics@surface@rICy}}

  %% One closed polygon: left free end, floor, right free end, then the
  %% complete inner boundary through both sharp miter points.
  \backgroundpath{%
    \pgfpathmoveto{\pgfpoint{\tikzphysics@surface@pb@lDx}{\tikzphysics@surface@pb@lDy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@lAx}{\tikzphysics@surface@pb@lAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rAx}{\tikzphysics@surface@pb@rAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rDx}{\tikzphysics@surface@pb@rDy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rCx}{\tikzphysics@surface@pb@rCy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rBx}{\tikzphysics@surface@pb@rBy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@lBx}{\tikzphysics@surface@pb@lBy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@lCx}{\tikzphysics@surface@pb@lCy}}%
    \pgfpathclose
  }
  %% One continuous contact line across the full bent platform.
  \foregroundpath{%
    \pgfsetlinewidth{0.5pt}%
    \pgfpathmoveto{\pgfpoint{\tikzphysics@surface@pb@lDx}{\tikzphysics@surface@pb@lDy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@lAx}{\tikzphysics@surface@pb@lAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rAx}{\tikzphysics@surface@pb@rAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rDx}{\tikzphysics@surface@pb@rDy}}%
    \pgfusepath{stroke}%
  }

  %% ---- fixed surface corners ----
  \anchor{left-corner}{\pgf@x=\tikzphysics@surface@pb@lICx \pgf@y=\tikzphysics@surface@pb@lICy}
  \anchor{right-corner}{\pgf@x=\tikzphysics@surface@pb@rICx \pgf@y=\tikzphysics@surface@pb@rICy}

  %% ---- floor anchors (fixed) ----
  \anchor{floor-tl}{\pgf@x=-\tikzphysics@surface@pb@hx \pgf@y=\tikzphysics@surface@pb@hy}
  \anchor{floor-tr}{\pgf@x= \tikzphysics@surface@pb@hx \pgf@y=\tikzphysics@surface@pb@hy}
  \anchor{floor-br}{\pgf@x= \tikzphysics@surface@pb@hx
                     \pgf@y=\dimexpr\tikzphysics@surface@pb@hy-\tikzphysics@surface@pb@sw\relax}
  \anchor{floor-bl}{\pgf@x=-\tikzphysics@surface@pb@hx
                     \pgf@y=\dimexpr\tikzphysics@surface@pb@hy-\tikzphysics@surface@pb@sw\relax}
  \anchor{floor-top-mid}   {\pgf@x=0pt \pgf@y=\tikzphysics@surface@pb@hy}
  \anchor{floor-bottom-mid}{\pgf@x=0pt
                     \pgf@y=\dimexpr\tikzphysics@surface@pb@hy-\tikzphysics@surface@pb@sw\relax}
  \anchor{floor-center}    {\pgf@x=0pt
     \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pb@hy-0.5*\tikzphysics@surface@pb@sw}}

  %% ---- left wall corners ----
  \anchor{left-wall-A}{\pgf@x=\tikzphysics@surface@pb@lAx \pgf@y=\tikzphysics@surface@pb@lAy}
  \anchor{left-wall-B}{\pgf@x=\tikzphysics@surface@pb@lBx \pgf@y=\tikzphysics@surface@pb@lBy}
  \anchor{left-wall-C}{\pgf@x=\tikzphysics@surface@pb@lCx \pgf@y=\tikzphysics@surface@pb@lCy}
  \anchor{left-wall-D}{\pgf@x=\tikzphysics@surface@pb@lDx \pgf@y=\tikzphysics@surface@pb@lDy}
  \anchor{left-wall-outer-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@lAx+\tikzphysics@surface@pb@lDx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@lAy+\tikzphysics@surface@pb@lDy)/2}}
  \anchor{left-wall-inner-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@lBx+\tikzphysics@surface@pb@lCx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@lBy+\tikzphysics@surface@pb@lCy)/2}}
  \anchor{left-wall-far-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@lCx+\tikzphysics@surface@pb@lDx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@lCy+\tikzphysics@surface@pb@lDy)/2}}
  \anchor{left-wall-near-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@lAx+\tikzphysics@surface@pb@lBx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@lAy+\tikzphysics@surface@pb@lBy)/2}}

  %% ---- right wall corners ----
  \anchor{right-wall-A}{\pgf@x=\tikzphysics@surface@pb@rAx \pgf@y=\tikzphysics@surface@pb@rAy}
  \anchor{right-wall-B}{\pgf@x=\tikzphysics@surface@pb@rBx \pgf@y=\tikzphysics@surface@pb@rBy}
  \anchor{right-wall-C}{\pgf@x=\tikzphysics@surface@pb@rCx \pgf@y=\tikzphysics@surface@pb@rCy}
  \anchor{right-wall-D}{\pgf@x=\tikzphysics@surface@pb@rDx \pgf@y=\tikzphysics@surface@pb@rDy}
  \anchor{right-wall-outer-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@rAx+\tikzphysics@surface@pb@rDx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@rAy+\tikzphysics@surface@pb@rDy)/2}}
  \anchor{right-wall-inner-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@rBx+\tikzphysics@surface@pb@rCx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@rBy+\tikzphysics@surface@pb@rCy)/2}}
  \anchor{right-wall-far-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@rCx+\tikzphysics@surface@pb@rDx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@rCy+\tikzphysics@surface@pb@rDy)/2}}
  \anchor{right-wall-near-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@rAx+\tikzphysics@surface@pb@rBx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@rAy+\tikzphysics@surface@pb@rBy)/2}}

  %% ---- numeric edge anchors on the floor ----
  \tikzphysics@declareedgeanchors{floor-bottom}
    {-\tikzphysics@surface@pb@hx}{\dimexpr\tikzphysics@surface@pb@hy-\tikzphysics@surface@pb@sw\relax}
    {\tikzphysics@surface@pb@hx}{\dimexpr\tikzphysics@surface@pb@hy-\tikzphysics@surface@pb@sw\relax}
  \tikzphysics@declareedgeanchors{floor-right}
    {\tikzphysics@surface@pb@hx}{\dimexpr\tikzphysics@surface@pb@hy-\tikzphysics@surface@pb@sw\relax}
    {\tikzphysics@surface@pb@hx}{\tikzphysics@surface@pb@hy}
  \tikzphysics@declareedgeanchors{floor-top}
    {\tikzphysics@surface@pb@hx}{\tikzphysics@surface@pb@hy}
    {-\tikzphysics@surface@pb@hx}{\tikzphysics@surface@pb@hy}
  \tikzphysics@declareedgeanchors{floor-left}
    {-\tikzphysics@surface@pb@hx}{\tikzphysics@surface@pb@hy}
    {-\tikzphysics@surface@pb@hx}{\dimexpr\tikzphysics@surface@pb@hy-\tikzphysics@surface@pb@sw\relax}

  %% ---- numeric edge anchors on the left wall ----
  \tikzphysics@declareedgeanchors{left-wall-outer}
    {\tikzphysics@surface@pb@lAx}{\tikzphysics@surface@pb@lAy}
    {\tikzphysics@surface@pb@lDx}{\tikzphysics@surface@pb@lDy}
  \tikzphysics@declareedgeanchors{left-wall-inner}
    {\tikzphysics@surface@pb@lBx}{\tikzphysics@surface@pb@lBy}
    {\tikzphysics@surface@pb@lCx}{\tikzphysics@surface@pb@lCy}
  \tikzphysics@declareedgeanchors{left-wall-near}
    {\tikzphysics@surface@pb@lAx}{\tikzphysics@surface@pb@lAy}
    {\tikzphysics@surface@pb@lBx}{\tikzphysics@surface@pb@lBy}
  \tikzphysics@declareedgeanchors{left-wall-far}
    {\tikzphysics@surface@pb@lDx}{\tikzphysics@surface@pb@lDy}
    {\tikzphysics@surface@pb@lCx}{\tikzphysics@surface@pb@lCy}

  %% ---- numeric edge anchors on the right wall ----
  \tikzphysics@declareedgeanchors{right-wall-outer}
    {\tikzphysics@surface@pb@rAx}{\tikzphysics@surface@pb@rAy}
    {\tikzphysics@surface@pb@rDx}{\tikzphysics@surface@pb@rDy}
  \tikzphysics@declareedgeanchors{right-wall-inner}
    {\tikzphysics@surface@pb@rBx}{\tikzphysics@surface@pb@rBy}
    {\tikzphysics@surface@pb@rCx}{\tikzphysics@surface@pb@rCy}
  \tikzphysics@declareedgeanchors{right-wall-near}
    {\tikzphysics@surface@pb@rAx}{\tikzphysics@surface@pb@rAy}
    {\tikzphysics@surface@pb@rBx}{\tikzphysics@surface@pb@rBy}
  \tikzphysics@declareedgeanchors{right-wall-far}
    {\tikzphysics@surface@pb@rDx}{\tikzphysics@surface@pb@rDy}
    {\tikzphysics@surface@pb@rCx}{\tikzphysics@surface@pb@rCy}

}

%% ============================================================
%%  WEDGE SHAPE
%%
%%  Individual savedmacros, one per dim.  See platform comment
%%  about why we avoid the "bundle of \def's" pattern.
%% ============================================================

%% Contact anchors follow the usable slope from left to right in every
%% mode; existing CCW edge families keep their original meanings.
\def\tikzphysics@surface@guidevalue{0.5cm}
\tikzset{
  surface guide length/.code={\def\tikzphysics@surface@guidevalue{#1}},
  surface guide length/.value required,
  physics surface guide length/.style={surface guide length={#1}},
  physics surface guide length/.value required,
}
\def\tikzphysics@surface@contactpoint#1#2{%
  \def\tikzphysics@surface@mode@bl{bl}%
  \def\tikzphysics@surface@mode@top{top}%
  \def\tikzphysics@surface@contact@right{right}%
  \def\tikzphysics@surface@contact@which{#2}%
  \def\tikzphysics@surface@contact@descending{0}%
  \ifx\tikzphysics@surface@w@ra\tikzphysics@surface@mode@bl
    \def\tikzphysics@surface@contact@descending{1}%
  \fi
  \ifx\tikzphysics@surface@w@ra\tikzphysics@surface@mode@top
    \ifx\tikzphysics@surface@contact@which\tikzphysics@surface@contact@right
      \def\tikzphysics@surface@contact@descending{1}%
    \fi
  \fi
  \ifnum\tikzphysics@surface@contact@descending=1
    \pgfmathsetlength{\pgf@x}{\tikzphysics@surface@w@tx+(#1/100)*(\tikzphysics@surface@w@hx-\tikzphysics@surface@w@tx)}%
    \pgfmathsetlength{\pgf@y}{(1-2*#1/100)*\tikzphysics@surface@w@hy}%
    \pgfmathsetmacro{\tikzphysics@surface@contact@angle}{atan2(-2*\tikzphysics@surface@w@hy,\tikzphysics@surface@w@hx-\tikzphysics@surface@w@tx)}%
  \else
    \pgfmathsetlength{\pgf@x}{-\tikzphysics@surface@w@hx+(#1/100)*(\tikzphysics@surface@w@hx+\tikzphysics@surface@w@tx)}%
    \pgfmathsetlength{\pgf@y}{(-1+2*#1/100)*\tikzphysics@surface@w@hy}%
    \pgfmathsetmacro{\tikzphysics@surface@contact@angle}{atan2(2*\tikzphysics@surface@w@hy,\tikzphysics@surface@w@hx+\tikzphysics@surface@w@tx)}%
  \fi
}
\def\tikzphysics@surface@contactguide#1#2#3{%
  \tikzphysics@surface@contactpoint{#1}{#2}%
  \edef\tikzphysics@surface@contact@x{\the\pgf@x}%
  \edef\tikzphysics@surface@contact@y{\the\pgf@y}%
  \ifnum#3=0
    \pgfmathsetlength{\pgf@x}{\tikzphysics@surface@contact@x-\tikzphysics@surface@w@guide*sin(\tikzphysics@surface@contact@angle)}%
    \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@contact@y+\tikzphysics@surface@w@guide*cos(\tikzphysics@surface@contact@angle)}%
  \else
    \pgfmathsetlength{\pgf@x}{\tikzphysics@surface@contact@x+#3*0.5*\tikzphysics@surface@w@guide*cos(\tikzphysics@surface@contact@angle)}%
    \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@contact@y+#3*0.5*\tikzphysics@surface@w@guide*sin(\tikzphysics@surface@contact@angle)}%
  \fi
}
\def\tikzphysics@surface@declarecontact@one#1{%
  \anchor{surface-#1}{\tikzphysics@surface@contactpoint{#1}{left}}%
  \anchor{tangent-before-#1}{\tikzphysics@surface@contactguide{#1}{left}{-1}}%
  \anchor{tangent-after-#1}{\tikzphysics@surface@contactguide{#1}{left}{1}}%
  \anchor{normal-#1}{\tikzphysics@surface@contactguide{#1}{left}{0}}%
  \anchor{right-surface-#1}{\tikzphysics@surface@contactpoint{#1}{right}}%
  \anchor{right-tangent-before-#1}{\tikzphysics@surface@contactguide{#1}{right}{-1}}%
  \anchor{right-tangent-after-#1}{\tikzphysics@surface@contactguide{#1}{right}{1}}%
  \anchor{right-normal-#1}{\tikzphysics@surface@contactguide{#1}{right}{0}}%
}
\def\tikzphysics@surface@declarecontactanchors{%
  \foreach \tikzphysics@@t in {0,1,...,100}{%
    \edef\tikzphysics@@partial{\noexpand\tikzphysics@surface@declarecontact@one{\tikzphysics@@t}}%
    \tikzphysics@@partial
  }%
}

\pgfdeclareshape{physicswedge}{
  \savedmacro{\tikzphysics@surface@w@guide}{%
    \tikzphysics@resolve@length{\@tempdima}{\tikzphysics@surface@guidevalue}%
    \edef\tikzphysics@surface@w@guide{\the\@tempdima}%
  }
  \anchor{surface-start}{\tikzphysics@surface@contactpoint{0}{left}}
  \anchor{surface-end}{\tikzphysics@surface@contactpoint{100}{left}}
  \tikzphysics@surface@declarecontactanchors

  \inheritsavedanchors[from=rectangle]
  \inheritanchorborder[from=rectangle]

  \savedmacro{\tikzphysics@surface@w@hx}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@hx{\the\tikzphysics@surface@hx}%
  }
  \savedmacro{\tikzphysics@surface@w@hy}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@hy{\the\tikzphysics@surface@hy}%
  }
  \savedmacro{\tikzphysics@surface@w@tx}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@tx{\the\tikzphysics@surface@tx}%
  }
  \savedmacro{\tikzphysics@surface@w@ra}{%
    \edef\tikzphysics@surface@w@ra{\tikzphysics@surface@wedgeraq}%
  }
  \savedmacro{\tikzphysics@surface@w@ang}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@ang{\tikzphysics@surface@ang}%
  }

  %% ---- bounding-box anchors ----
  \anchor{center}    {\pgf@x=0pt                 \pgf@y=0pt}
  \anchor{north}     {\pgf@x=0pt                 \pgf@y=\tikzphysics@surface@w@hy}
  \anchor{south}     {\pgf@x=0pt                 \pgf@y=-\tikzphysics@surface@w@hy}
  \anchor{east}      {\pgf@x=\tikzphysics@surface@w@hx   \pgf@y=0pt}
  \anchor{west}      {\pgf@x=-\tikzphysics@surface@w@hx  \pgf@y=0pt}
  \anchor{north east}{\pgf@x=\tikzphysics@surface@w@hx   \pgf@y=\tikzphysics@surface@w@hy}
  \anchor{north west}{\pgf@x=-\tikzphysics@surface@w@hx  \pgf@y=\tikzphysics@surface@w@hy}
  \anchor{south east}{\pgf@x=\tikzphysics@surface@w@hx   \pgf@y=-\tikzphysics@surface@w@hy}
  \anchor{south west}{\pgf@x=-\tikzphysics@surface@w@hx  \pgf@y=-\tikzphysics@surface@w@hy}

  %% ---- physics anchors ----

  %% base corners and apex are identical in formula across modes,
  %% because tx = -hx for bl, +hx for br, and the Thales x for top.
  \anchor{bl}  {\pgf@x=-\tikzphysics@surface@w@hx \pgf@y=-\tikzphysics@surface@w@hy}
  \anchor{br}  {\pgf@x=\tikzphysics@surface@w@hx  \pgf@y=-\tikzphysics@surface@w@hy}
  \anchor{top} {\pgf@x=\tikzphysics@surface@w@tx  \pgf@y=\tikzphysics@surface@w@hy}

  %% base-mid: midpoint of bl--br. Always (0, -hy).
  \anchor{base-mid}{\pgf@x=0pt \pgf@y=-\tikzphysics@surface@w@hy}

  %% right-mid: midpoint of the right-angle-adjacent non-base leg.
  %%   bl  mode: leg is (-hx,-hy)--(-hx,+hy), mid = (-hx, 0) = (tx, 0)
  %%   br  mode: leg is (+hx,-hy)--(+hx,+hy), mid = (+hx, 0) = (tx, 0)
  %%   top mode: no single "right-angle leg"; falls out as (tx, 0),
  %%             the vertical centre of the apex column.
  \anchor{right-mid}{\pgf@x=\tikzphysics@surface@w@tx \pgf@y=0pt}

  %% slope-mid: midpoint of the hypotenuse (sloped side).
  %%   bl mode:  br (+hx,-hy) -> apex (-hx,+hy), mid = (0, 0)
  %%   br mode:  bl (-hx,-hy) -> apex (+hx,+hy), mid = (0, 0)
  %%   top mode: the hypotenuse IS the base; we return the midpoint
  %%             of the LEFT leg for a useful "where a block sits
  %%             on the left slope" value.  Use slope-right-mid for
  %%             the right leg.
  \anchor{slope-mid}{%
    \def\tikzphysics@surface@ra@top{top}%
    \ifx\tikzphysics@surface@w@ra\tikzphysics@surface@ra@top
      \pgfmathsetlength{\pgf@x}{(-\tikzphysics@surface@w@hx+\tikzphysics@surface@w@tx)/2}%
      \pgf@y=0pt
    \else
      \pgf@x=0pt \pgf@y=0pt
    \fi
  }

  %% slope-right-mid: only meaningful in top mode; mid of apex--br.
  %%   Elsewhere this equals slope-mid for consistency.
  \anchor{slope-right-mid}{%
    \def\tikzphysics@surface@ra@top{top}%
    \ifx\tikzphysics@surface@w@ra\tikzphysics@surface@ra@top
      \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@w@hx+\tikzphysics@surface@w@tx)/2}%
      \pgf@y=0pt
    \else
      \pgf@x=0pt \pgf@y=0pt
    \fi
  }

  %% centroid = (bl + br + apex) / 3
  %%   = ((-hx + hx + tx)/3, (-hy - hy + hy)/3)
  %%   = (tx/3, -hy/3)   for ALL modes.
  \anchor{centroid}{%
    \pgfmathsetlength{\pgf@x}{\tikzphysics@surface@w@tx/3}%
    \pgfmathsetlength{\pgf@y}{-\tikzphysics@surface@w@hy/3}%
  }
  \anchor{mid}{%
    \pgfmathsetlength{\pgf@x}{\tikzphysics@surface@w@tx/3}%
    \pgfmathsetlength{\pgf@y}{-\tikzphysics@surface@w@hy/3}%
  }

  %% ---- background (fill/pattern) path ----
  %% Single triangle: bl -> br -> apex, where apex = (tx, hy)
  %% regardless of mode.
  \backgroundpath{%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@w@hx}{-\tikzphysics@surface@w@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@hx}{-\tikzphysics@surface@w@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}}%
    \pgfpathclose%
  }

  %% ---- numeric edge anchors (CCW from bl on the triangle) ----
  %% base : bl -> br           (base-0 at bl,  base-100 at br)
  %% right: br -> apex         (right-0 at br, right-100 at apex)
  %% slope: apex -> bl         (slope-0 at apex, slope-100 at foot bl)
  %%
  %% In `physics wedge right angle at=br' (the default) the names match
  %% physics intuition: right is the vertical leg, slope is the
  %% hypotenuse.  In bl and top modes, the names still follow
  %% pure CCW ordering from bl, so `right' and `slope' refer to
  %% whichever geometric edges CCW yields (see the docs for what
  %% they mean in each mode).
  \tikzphysics@declareedgeanchors{base}
    {-\tikzphysics@surface@w@hx}{-\tikzphysics@surface@w@hy}
    {\tikzphysics@surface@w@hx}{-\tikzphysics@surface@w@hy}
  \tikzphysics@declareedgeanchors{right}
    {\tikzphysics@surface@w@hx}{-\tikzphysics@surface@w@hy}
    {\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}
  \tikzphysics@declareedgeanchors{slope}
    {\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}
    {-\tikzphysics@surface@w@hx}{-\tikzphysics@surface@w@hy}
}

%% Snapshot scalar geometry for \geometryvalue after a named wedge is built.
%% Interior angles are at the semantic vertices bl, br, and top. Edge
%% directions rise toward top; slope placement directions instead run along
%% the corresponding contact surface and can be passed directly to rotate.
\def\tikzphysics@surface@wedgegeometry@bl{%
  \def\tikzphysics@surface@g@leftangle{90}%
  \edef\tikzphysics@surface@g@rightangle{\tikzphysics@surface@g@inputangle}%
  \pgfmathsetmacro{\tikzphysics@surface@g@topangle}{90-\tikzphysics@surface@g@inputangle}%
  \def\tikzphysics@surface@g@leftdirection{90}%
  \pgfmathsetmacro{\tikzphysics@surface@g@rightdirection}{180-\tikzphysics@surface@g@inputangle}%
  \pgfmathsetmacro{\tikzphysics@surface@g@slopedirection}{-\tikzphysics@surface@g@inputangle}%
  \edef\tikzphysics@surface@g@rightslopedirection{\tikzphysics@surface@g@slopedirection}%
}
\def\tikzphysics@surface@wedgegeometry@br{%
  \edef\tikzphysics@surface@g@leftangle{\tikzphysics@surface@g@inputangle}%
  \def\tikzphysics@surface@g@rightangle{90}%
  \pgfmathsetmacro{\tikzphysics@surface@g@topangle}{90-\tikzphysics@surface@g@inputangle}%
  \edef\tikzphysics@surface@g@leftdirection{\tikzphysics@surface@g@inputangle}%
  \edef\tikzphysics@surface@g@slopedirection{\tikzphysics@surface@g@inputangle}%
  \edef\tikzphysics@surface@g@rightslopedirection{\tikzphysics@surface@g@slopedirection}%
  \def\tikzphysics@surface@g@rightdirection{90}%
}
\def\tikzphysics@surface@wedgegeometry@top{%
  \edef\tikzphysics@surface@g@leftangle{\tikzphysics@surface@g@inputangle}%
  \pgfmathsetmacro{\tikzphysics@surface@g@rightangle}{90-\tikzphysics@surface@g@inputangle}%
  \def\tikzphysics@surface@g@topangle{90}%
  \edef\tikzphysics@surface@g@leftdirection{\tikzphysics@surface@g@inputangle}%
  \edef\tikzphysics@surface@g@slopedirection{\tikzphysics@surface@g@inputangle}%
  \pgfmathsetmacro{\tikzphysics@surface@g@rightdirection}{90+\tikzphysics@surface@g@inputangle}%
  \pgfmathsetmacro{\tikzphysics@surface@g@rightslopedirection}{\tikzphysics@surface@g@inputangle-90}%
}

\newcommand{\tikzphysics@surface@recordwedgegeometry}[1]{%
  \begingroup
    \ifcsname pgf@sh@ma@#1\endcsname
      \csname pgf@sh@ma@#1\endcsname
      \edef\tikzphysics@surface@g@inputangle{\tikzphysics@surface@w@ang}%
      \edef\tikzphysics@surface@g@mode{\tikzphysics@surface@w@ra}%
      \csname tikzphysics@surface@wedgegeometry@\tikzphysics@surface@g@mode\endcsname
      \@tempdima=\tikzphysics@surface@w@hx\relax
      \multiply\@tempdima by 2
      \edef\tikzphysics@surface@g@width{\the\@tempdima}%
      \@tempdima=\tikzphysics@surface@w@hy\relax
      \multiply\@tempdima by 2
      \edef\tikzphysics@surface@g@height{\the\@tempdima}%
      \tikzphysics@storegeometryvalue{#1}{left angle}{\tikzphysics@surface@g@leftangle}%
      \tikzphysics@storegeometryvalue{#1}{right angle}{\tikzphysics@surface@g@rightangle}%
      \tikzphysics@storegeometryvalue{#1}{top angle}{\tikzphysics@surface@g@topangle}%
      \tikzphysics@storegeometryvalue{#1}{base direction}{0}%
      \tikzphysics@storegeometryvalue{#1}{slope direction}{\tikzphysics@surface@g@slopedirection}%
      \tikzphysics@storegeometryvalue{#1}{left edge direction}{\tikzphysics@surface@g@leftdirection}%
      \tikzphysics@storegeometryvalue{#1}{right edge direction}{\tikzphysics@surface@g@rightdirection}%
      \tikzphysics@storegeometryvalue{#1}{base angle}{0}%
      \tikzphysics@storegeometryvalue{#1}{slope angle}{\tikzphysics@surface@g@slopedirection}%
      \tikzphysics@storegeometryvalue{#1}{surface angle}{\tikzphysics@surface@g@slopedirection}%
      \tikzphysics@storegeometryvalue{#1}{right slope angle}{\tikzphysics@surface@g@rightslopedirection}%
      \tikzphysics@storegeometryvalue{#1}{right edge angle}{\tikzphysics@surface@g@rightdirection}%
      \tikzphysics@storegeometryvalue{#1}{width}{\tikzphysics@surface@g@width}%
      \tikzphysics@storegeometryvalue{#1}{height}{\tikzphysics@surface@g@height}%
      \tikzphysics@storegeometryvalue{#1}{right angle at}{\tikzphysics@surface@g@mode}%
    \fi
  \endgroup
}

\tikzphysics@registergeometryrecorder{physicswedge}{\tikzphysics@surface@recordwedgegeometry}

%% ============================================================
%%  FLAT / WALL / CEILING SHAPES
%%
%%  Four thin rectangular shapes that share the same sizing
%%  primitive but differ in which edge carries the "surface"
%%  foreground line (and hence which side is the usable face):
%%
%%    physicsground    : surface on TOP edge  (6cm x 0.4cm default)
%%    physicsceiling   : surface on BOTTOM edge (2cm x 0.4cm default)
%%    physicswallleft  : surface on RIGHT edge (hatching appears on
%%                   the left side of the strip - so a "left
%%                   wall" whose usable face is its right edge)
%%                  default 0.4cm x 3cm (thickness x height)
%%    physicswallright : mirror of physicswallleft - surface on LEFT edge
%%
%%  Patterned hatching comes from the user-facing compound
%%  style (pattern=north east lines), not from the shape.
%%
%%  Anchors: 4 corners + 4 midpoints (top-mid, bottom-mid,
%%  left-mid, right-mid) + center, plus a convenience `surface'
%%  anchor that points at the useful face's midpoint.  Numeric
%%  edge anchors (bottom/right/top/left)-0..100 are declared
%%  CCW from bl on the bounding box.
%% ============================================================

\pgfdeclareshape{physicsground}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchorborder[from=rectangle]

  \savedmacro{\tikzphysics@surface@g@hx}{%
    \tikzphysics@surface@setflatdims
    \edef\tikzphysics@surface@g@hx{\the\tikzphysics@surface@hx}%
  }
  \savedmacro{\tikzphysics@surface@g@hy}{%
    \tikzphysics@surface@setflatdims
    \edef\tikzphysics@surface@g@hy{\the\tikzphysics@surface@hy}%
  }

  \backgroundpath{%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@g@hx}{-\tikzphysics@surface@g@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@g@hx}{-\tikzphysics@surface@g@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@g@hx}{\tikzphysics@surface@g@hy}}%
    \pgfpathlineto{\pgfpoint{-\tikzphysics@surface@g@hx}{\tikzphysics@surface@g@hy}}%
    \pgfpathclose%
  }
  \foregroundpath{%
    \pgfsetlinewidth{0.5pt}%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@g@hx}{\tikzphysics@surface@g@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@g@hx}{\tikzphysics@surface@g@hy}}%
    \pgfusepath{stroke}%
  }

  \anchor{top-left}    {\pgf@x=-\tikzphysics@surface@g@hx \pgf@y=\tikzphysics@surface@g@hy}
  \anchor{top-right}   {\pgf@x=\tikzphysics@surface@g@hx  \pgf@y=\tikzphysics@surface@g@hy}
  \anchor{top-mid}     {\pgf@x=0pt                \pgf@y=\tikzphysics@surface@g@hy}
  \anchor{bottom-left} {\pgf@x=-\tikzphysics@surface@g@hx \pgf@y=-\tikzphysics@surface@g@hy}
  \anchor{bottom-right}{\pgf@x=\tikzphysics@surface@g@hx  \pgf@y=-\tikzphysics@surface@g@hy}
  \anchor{bottom-mid}  {\pgf@x=0pt                \pgf@y=-\tikzphysics@surface@g@hy}
  \anchor{left-mid}    {\pgf@x=-\tikzphysics@surface@g@hx \pgf@y=0pt}
  \anchor{right-mid}   {\pgf@x=\tikzphysics@surface@g@hx  \pgf@y=0pt}
  \anchor{surface}     {\pgf@x=0pt                \pgf@y=\tikzphysics@surface@g@hy}

  %% ---- numeric edge anchors (CCW from bl, bounding box) ----
  \tikzphysics@declareedgeanchors{bottom}
    {-\tikzphysics@surface@g@hx}{-\tikzphysics@surface@g@hy}
    {\tikzphysics@surface@g@hx}{-\tikzphysics@surface@g@hy}
  \tikzphysics@declareedgeanchors{right}
    {\tikzphysics@surface@g@hx}{-\tikzphysics@surface@g@hy}
    {\tikzphysics@surface@g@hx}{\tikzphysics@surface@g@hy}
  \tikzphysics@declareedgeanchors{top}
    {\tikzphysics@surface@g@hx}{\tikzphysics@surface@g@hy}
    {-\tikzphysics@surface@g@hx}{\tikzphysics@surface@g@hy}
  \tikzphysics@declareedgeanchors{left}
    {-\tikzphysics@surface@g@hx}{\tikzphysics@surface@g@hy}
    {-\tikzphysics@surface@g@hx}{-\tikzphysics@surface@g@hy}
}

\pgfdeclareshape{physicsceiling}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchorborder[from=rectangle]

  \savedmacro{\tikzphysics@surface@c@hx}{%
    \tikzphysics@surface@setflatdims
    \edef\tikzphysics@surface@c@hx{\the\tikzphysics@surface@hx}%
  }
  \savedmacro{\tikzphysics@surface@c@hy}{%
    \tikzphysics@surface@setflatdims
    \edef\tikzphysics@surface@c@hy{\the\tikzphysics@surface@hy}%
  }

  \backgroundpath{%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@c@hx}{-\tikzphysics@surface@c@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@c@hx}{-\tikzphysics@surface@c@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@c@hx}{\tikzphysics@surface@c@hy}}%
    \pgfpathlineto{\pgfpoint{-\tikzphysics@surface@c@hx}{\tikzphysics@surface@c@hy}}%
    \pgfpathclose%
  }
  \foregroundpath{%
    \pgfsetlinewidth{0.5pt}%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@c@hx}{-\tikzphysics@surface@c@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@c@hx}{-\tikzphysics@surface@c@hy}}%
    \pgfusepath{stroke}%
  }

  \anchor{top-left}    {\pgf@x=-\tikzphysics@surface@c@hx \pgf@y=\tikzphysics@surface@c@hy}
  \anchor{top-right}   {\pgf@x=\tikzphysics@surface@c@hx  \pgf@y=\tikzphysics@surface@c@hy}
  \anchor{top-mid}     {\pgf@x=0pt                \pgf@y=\tikzphysics@surface@c@hy}
  \anchor{bottom-left} {\pgf@x=-\tikzphysics@surface@c@hx \pgf@y=-\tikzphysics@surface@c@hy}
  \anchor{bottom-right}{\pgf@x=\tikzphysics@surface@c@hx  \pgf@y=-\tikzphysics@surface@c@hy}
  \anchor{bottom-mid}  {\pgf@x=0pt                \pgf@y=-\tikzphysics@surface@c@hy}
  \anchor{left-mid}    {\pgf@x=-\tikzphysics@surface@c@hx \pgf@y=0pt}
  \anchor{right-mid}   {\pgf@x=\tikzphysics@surface@c@hx  \pgf@y=0pt}
  \anchor{surface}     {\pgf@x=0pt                \pgf@y=-\tikzphysics@surface@c@hy}

  %% ---- numeric edge anchors (CCW from bl, bounding box) ----
  \tikzphysics@declareedgeanchors{bottom}
    {-\tikzphysics@surface@c@hx}{-\tikzphysics@surface@c@hy}
    {\tikzphysics@surface@c@hx}{-\tikzphysics@surface@c@hy}
  \tikzphysics@declareedgeanchors{right}
    {\tikzphysics@surface@c@hx}{-\tikzphysics@surface@c@hy}
    {\tikzphysics@surface@c@hx}{\tikzphysics@surface@c@hy}
  \tikzphysics@declareedgeanchors{top}
    {\tikzphysics@surface@c@hx}{\tikzphysics@surface@c@hy}
    {-\tikzphysics@surface@c@hx}{\tikzphysics@surface@c@hy}
  \tikzphysics@declareedgeanchors{left}
    {-\tikzphysics@surface@c@hx}{\tikzphysics@surface@c@hy}
    {-\tikzphysics@surface@c@hx}{-\tikzphysics@surface@c@hy}
}

\pgfdeclareshape{physicswallleft}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchorborder[from=rectangle]

  \savedmacro{\tikzphysics@surface@wl@hx}{%
    \tikzphysics@surface@setflatdims
    \edef\tikzphysics@surface@wl@hx{\the\tikzphysics@surface@hx}%
  }
  \savedmacro{\tikzphysics@surface@wl@hy}{%
    \tikzphysics@surface@setflatdims
    \edef\tikzphysics@surface@wl@hy{\the\tikzphysics@surface@hy}%
  }

  \backgroundpath{%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@wl@hx}{-\tikzphysics@surface@wl@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@wl@hx}{-\tikzphysics@surface@wl@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@wl@hx}{\tikzphysics@surface@wl@hy}}%
    \pgfpathlineto{\pgfpoint{-\tikzphysics@surface@wl@hx}{\tikzphysics@surface@wl@hy}}%
    \pgfpathclose%
  }
  %% surface on RIGHT edge (usable face points to +x)
  \foregroundpath{%
    \pgfsetlinewidth{0.5pt}%
    \pgfpathmoveto{\pgfpoint{\tikzphysics@surface@wl@hx}{-\tikzphysics@surface@wl@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@wl@hx}{\tikzphysics@surface@wl@hy}}%
    \pgfusepath{stroke}%
  }

  \anchor{top-left}    {\pgf@x=-\tikzphysics@surface@wl@hx \pgf@y=\tikzphysics@surface@wl@hy}
  \anchor{top-right}   {\pgf@x=\tikzphysics@surface@wl@hx  \pgf@y=\tikzphysics@surface@wl@hy}
  \anchor{top-mid}     {\pgf@x=0pt                 \pgf@y=\tikzphysics@surface@wl@hy}
  \anchor{bottom-left} {\pgf@x=-\tikzphysics@surface@wl@hx \pgf@y=-\tikzphysics@surface@wl@hy}
  \anchor{bottom-right}{\pgf@x=\tikzphysics@surface@wl@hx  \pgf@y=-\tikzphysics@surface@wl@hy}
  \anchor{bottom-mid}  {\pgf@x=0pt                 \pgf@y=-\tikzphysics@surface@wl@hy}
  \anchor{left-mid}    {\pgf@x=-\tikzphysics@surface@wl@hx \pgf@y=0pt}
  \anchor{right-mid}   {\pgf@x=\tikzphysics@surface@wl@hx  \pgf@y=0pt}
  \anchor{surface}     {\pgf@x=\tikzphysics@surface@wl@hx  \pgf@y=0pt}

  %% ---- numeric edge anchors (CCW from bl, bounding box) ----
  \tikzphysics@declareedgeanchors{bottom}
    {-\tikzphysics@surface@wl@hx}{-\tikzphysics@surface@wl@hy}
    {\tikzphysics@surface@wl@hx}{-\tikzphysics@surface@wl@hy}
  \tikzphysics@declareedgeanchors{right}
    {\tikzphysics@surface@wl@hx}{-\tikzphysics@surface@wl@hy}
    {\tikzphysics@surface@wl@hx}{\tikzphysics@surface@wl@hy}
  \tikzphysics@declareedgeanchors{top}
    {\tikzphysics@surface@wl@hx}{\tikzphysics@surface@wl@hy}
    {-\tikzphysics@surface@wl@hx}{\tikzphysics@surface@wl@hy}
  \tikzphysics@declareedgeanchors{left}
    {-\tikzphysics@surface@wl@hx}{\tikzphysics@surface@wl@hy}
    {-\tikzphysics@surface@wl@hx}{-\tikzphysics@surface@wl@hy}
}

\pgfdeclareshape{physicswallright}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{south east}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchorborder[from=rectangle]

  \savedmacro{\tikzphysics@surface@wr@hx}{%
    \tikzphysics@surface@setflatdims
    \edef\tikzphysics@surface@wr@hx{\the\tikzphysics@surface@hx}%
  }
  \savedmacro{\tikzphysics@surface@wr@hy}{%
    \tikzphysics@surface@setflatdims
    \edef\tikzphysics@surface@wr@hy{\the\tikzphysics@surface@hy}%
  }

  \backgroundpath{%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@wr@hx}{-\tikzphysics@surface@wr@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@wr@hx}{-\tikzphysics@surface@wr@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@wr@hx}{\tikzphysics@surface@wr@hy}}%
    \pgfpathlineto{\pgfpoint{-\tikzphysics@surface@wr@hx}{\tikzphysics@surface@wr@hy}}%
    \pgfpathclose%
  }
  %% surface on LEFT edge (usable face points to -x)
  \foregroundpath{%
    \pgfsetlinewidth{0.5pt}%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@wr@hx}{-\tikzphysics@surface@wr@hy}}%
    \pgfpathlineto{\pgfpoint{-\tikzphysics@surface@wr@hx}{\tikzphysics@surface@wr@hy}}%
    \pgfusepath{stroke}%
  }

  \anchor{top-left}    {\pgf@x=-\tikzphysics@surface@wr@hx \pgf@y=\tikzphysics@surface@wr@hy}
  \anchor{top-right}   {\pgf@x=\tikzphysics@surface@wr@hx  \pgf@y=\tikzphysics@surface@wr@hy}
  \anchor{top-mid}     {\pgf@x=0pt                 \pgf@y=\tikzphysics@surface@wr@hy}
  \anchor{bottom-left} {\pgf@x=-\tikzphysics@surface@wr@hx \pgf@y=-\tikzphysics@surface@wr@hy}
  \anchor{bottom-right}{\pgf@x=\tikzphysics@surface@wr@hx  \pgf@y=-\tikzphysics@surface@wr@hy}
  \anchor{bottom-mid}  {\pgf@x=0pt                 \pgf@y=-\tikzphysics@surface@wr@hy}
  \anchor{left-mid}    {\pgf@x=-\tikzphysics@surface@wr@hx \pgf@y=0pt}
  \anchor{right-mid}   {\pgf@x=\tikzphysics@surface@wr@hx  \pgf@y=0pt}
  \anchor{surface}     {\pgf@x=-\tikzphysics@surface@wr@hx \pgf@y=0pt}

  %% ---- numeric edge anchors (CCW from bl, bounding box) ----
  \tikzphysics@declareedgeanchors{bottom}
    {-\tikzphysics@surface@wr@hx}{-\tikzphysics@surface@wr@hy}
    {\tikzphysics@surface@wr@hx}{-\tikzphysics@surface@wr@hy}
  \tikzphysics@declareedgeanchors{right}
    {\tikzphysics@surface@wr@hx}{-\tikzphysics@surface@wr@hy}
    {\tikzphysics@surface@wr@hx}{\tikzphysics@surface@wr@hy}
  \tikzphysics@declareedgeanchors{top}
    {\tikzphysics@surface@wr@hx}{\tikzphysics@surface@wr@hy}
    {-\tikzphysics@surface@wr@hx}{\tikzphysics@surface@wr@hy}
  \tikzphysics@declareedgeanchors{left}
    {-\tikzphysics@surface@wr@hx}{\tikzphysics@surface@wr@hy}
    {-\tikzphysics@surface@wr@hx}{-\tikzphysics@surface@wr@hy}
}

%% ============================================================
%%  ANCHOR AND KEY REGISTRATION (for debug overlays)
%% ============================================================

\tikzphysics@registeranchors{physicsplatformleft}{%
  corner, floor-tl, floor-tr, floor-br, floor-bl,
  floor-top-mid, floor-bottom-mid, floor-left-mid, floor-right-mid,
  floor-center, wall-A, wall-B, wall-C, wall-D,
  wall-outer-mid, wall-inner-mid, wall-near-mid, wall-far-mid,
  wall-center, center}
\tikzphysics@registeranchors{physicsplatformright}{%
  corner, floor-tl, floor-tr, floor-br, floor-bl,
  floor-top-mid, floor-bottom-mid, floor-left-mid, floor-right-mid,
  floor-center, wall-A, wall-B, wall-C, wall-D,
  wall-outer-mid, wall-inner-mid, wall-near-mid, wall-far-mid,
  wall-center, center}
\tikzphysics@registeranchors{physicsplatformboth}{%
  left-corner, right-corner, floor-tl, floor-tr, floor-br, floor-bl,
  floor-top-mid, floor-bottom-mid, floor-center,
  left-wall-A, left-wall-B, left-wall-C, left-wall-D,
  left-wall-outer-mid, left-wall-inner-mid,
  left-wall-near-mid, left-wall-far-mid,
  right-wall-A, right-wall-B, right-wall-C, right-wall-D,
  right-wall-outer-mid, right-wall-inner-mid,
  right-wall-near-mid, right-wall-far-mid, center}
\tikzphysics@registeranchors{physicswedge}{%
  bl, br, top, base-mid, slope-mid, slope-right-mid,
  surface-start, surface-end, surface-50, normal-50,
  right-mid, centroid, center, north, south, east, west}
\tikzphysics@registeranchors{physicsground}{%
  top-left, top-right, top-mid, left-mid, right-mid,
  bottom-left, bottom-right, bottom-mid, surface, center}
\tikzphysics@registeranchors{physicsceiling}{%
  top-left, top-right, top-mid, left-mid, right-mid,
  bottom-left, bottom-right, bottom-mid, surface, center}
\tikzphysics@registeranchors{physicswallleft}{%
  top-left, top-right, top-mid, left-mid, right-mid,
  bottom-left, bottom-right, bottom-mid, surface, center}
\tikzphysics@registeranchors{physicswallright}{%
  top-left, top-right, top-mid, left-mid, right-mid,
  bottom-left, bottom-right, bottom-mid, surface, center}

\tikzphysics@registerdisplayname{physicsplatformleft}{platform-left}
\tikzphysics@registerdisplayname{physicsplatformright}{platform-right}
\tikzphysics@registerdisplayname{physicsplatformboth}{platform}
\tikzphysics@registerdisplayname{physicswedge}{wedge}
\tikzphysics@registerdisplayname{physicsground}{ground}
\tikzphysics@registerdisplayname{physicsceiling}{ceiling}
\tikzphysics@registerdisplayname{physicswallleft}{wall-left}
\tikzphysics@registerdisplayname{physicswallright}{wall-right}

\tikzphysics@registerkeys{physicsplatformleft}{%
  minimum width, minimum height, strip width, wall angle}
\tikzphysics@registerkeydefaults{physicsplatformleft}{%
  minimum width/5cm, minimum height/2cm, strip width/0.25cm, wall angle/$-90^\circ$}
\tikzphysics@registerkeys{physicsplatformright}{%
  minimum width, minimum height, strip width, wall angle}
\tikzphysics@registerkeydefaults{physicsplatformright}{%
  minimum width/5cm, minimum height/2cm, strip width/0.25cm, wall angle/$-90^\circ$}
\tikzphysics@registerkeys{physicsplatformboth}{%
  minimum width, minimum height, strip width,
  wall angle, left wall angle, right wall angle}
\tikzphysics@registerkeydefaults{physicsplatformboth}{%
  minimum width/5cm, minimum height/2cm, strip width/0.25cm,
  wall angle/$-90^\circ$, left wall angle/$-90^\circ$, right wall angle/$-90^\circ$}
\tikzphysics@registerkeys{physicswedge}{%
  minimum width, wedge height, wedge angle, wedge right angle at}
\tikzphysics@registerkeydefaults{physicswedge}{%
  minimum width/4cm, wedge height/derived, wedge angle/$30^\circ$, wedge right angle at/br, surface guide length/0.5cm}
\tikzphysics@registerkeys{physicsground}{%
  minimum width, minimum height}
\tikzphysics@registerkeydefaults{physicsground}{%
  minimum width/6cm, minimum height/0.3cm}
\tikzphysics@registerkeys{physicsceiling}{%
  minimum width, minimum height}
\tikzphysics@registerkeydefaults{physicsceiling}{%
  minimum width/2cm, minimum height/0.3cm}
\tikzphysics@registerkeys{physicswallleft}{%
  minimum width, minimum height}
\tikzphysics@registerkeydefaults{physicswallleft}{%
  minimum width/0.3cm, minimum height/3cm}
\tikzphysics@registerkeys{physicswallright}{%
  minimum width, minimum height}
\tikzphysics@registerkeydefaults{physicswallright}{%
  minimum width/0.3cm, minimum height/3cm}

%% ============================================================
%%  COMPOUND NODE STYLES
%% ============================================================

\tikzset{
  physicsplatform-left/.style={
    shape=physicsplatformleft,
    physics logical shape=physicsplatformleft,
    anchor=floor-tl,
    draw=none,
    fill=white,
    pattern=north east lines,
    pattern color=black,
    inner sep=0pt,
    outer sep=0pt,
    minimum width=5cm,
    minimum height=2cm,
    physics debug setup, every physics object, every platform,
  },
  physicsplatform-right/.style={
    shape=physicsplatformright,
    physics logical shape=physicsplatformright,
    anchor=floor-tr,
    draw=none,
    fill=white,
    pattern=north east lines,
    pattern color=black,
    inner sep=0pt,
    outer sep=0pt,
    minimum width=5cm,
    minimum height=2cm,
    physics debug setup, every physics object, every platform,
  },
  physicsplatform-left-up/.style={physicsplatform-left, wall angle=90},
  physicsplatform-right-up/.style={physicsplatform-right, wall angle=90},
  physicsplatform-both/.style={
    shape=physicsplatformboth,
    physics logical shape=physicsplatformboth,
    anchor=floor-top-mid,
    draw=none,
    fill=white,
    pattern=north east lines,
    pattern color=black,
    inner sep=0pt,
    outer sep=0pt,
    minimum width=5cm,
    minimum height=2cm,
    physics debug setup, every physics object, every platform,
  },
  physicswedge/.style={
    shape=physicswedge,
    physics logical shape=physicswedge,
    physics geometry shape=physicswedge,
    physics logical shape=physicswedge,
    physics logical shape=physicswedge,
    anchor=bl,
    draw=black,
    line width=0.5pt,
    fill=none,
    pattern=dots,
    pattern color=black,
    inner sep=0pt,
    outer sep=0pt,
    minimum width=4cm,
    minimum height=3cm,
    physics debug setup, every physics object, every wedge,
  },
  physicsground/.style={
    shape=physicsground,
    physics logical shape=physicsground,
    anchor=top-mid,
    draw=none,
    fill=white,
    pattern=north east lines,
    pattern color=black,
    inner sep=0pt,
    outer sep=0pt,
    minimum width=6cm,
    minimum height=0.3cm,
    physics debug setup, every physics object, every ground,
  },
  physicsceiling/.style={
    shape=physicsceiling,
    physics logical shape=physicsceiling,
    anchor=bottom-mid,
    draw=none,
    fill=white,
    pattern=north east lines,
    pattern color=black,
    inner sep=0pt,
    outer sep=0pt,
    minimum width=2cm,
    minimum height=0.3cm,
    physics debug setup, every physics object, every ceiling,
  },
  physicswall-left/.style={
    shape=physicswallleft,
    physics logical shape=physicswallleft,
    anchor=right-mid,
    draw=none,
    fill=white,
    pattern=north east lines,
    pattern color=black,
    inner sep=0pt,
    outer sep=0pt,
    minimum width=0.3cm,
    minimum height=3cm,
    physics debug setup, every physics object, every wall-left,
  },
  physicswall-right/.style={
    shape=physicswallright,
    physics logical shape=physicswallright,
    anchor=left-mid,
    draw=none,
    fill=white,
    pattern=north east lines,
    pattern color=black,
    inner sep=0pt,
    outer sep=0pt,
    minimum width=0.3cm,
    minimum height=3cm,
    physics debug setup, every physics object, every wall-right,
  },
}

%% Short public names.  The physics-prefixed styles above remain available
%% when a document or another TikZ library already uses a generic name.
\tikzset{
  platform/.style={physicsplatform-both},
  platform-left/.style={physicsplatform-left},
  platform-right/.style={physicsplatform-right},
  platform-left-up/.style={physicsplatform-left-up},
  platform-right-up/.style={physicsplatform-right-up},
  platform-both/.style={physicsplatform-both},
  wedge/.style={physicswedge},
  ground/.style={physicsground},
  ceiling/.style={physicsceiling},
  wall-left/.style={physicswall-left},
  wall-right/.style={physicswall-right},
}

\tikzset{
  physics platform width/.value required,
  physics platform depth/.value required,
  physics strip width/.value required,
  physics wall angle/.value required,
  physics left wall angle/.value required,
  physics right wall angle/.value required,
  physics wedge width/.value required,
  physics wedge height/.value required,
  physics wedge angle/.value required,
  physics ground width/.value required,
  physics ground depth/.value required,
  physics ceiling width/.value required,
  physics ceiling depth/.value required,
  physics wall thickness/.value required,
  physics wall height/.value required,
  surface guide length/.value required,
}
\makeatother
\endinput
%%
%% End of file `tikzlibrarytikzphysics.surface.code.tex'.
