%% 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.5.0 (2026-09-26)
%% 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
\newdimen\tikzphysics@surface@wi    %% wall inset from the floor tip
\newdimen\tikzphysics@surface@wd    %% wall drop before the wall begins
\newdimen\tikzphysics@surface@wwi   %% wedge top inset
\newdimen\tikzphysics@surface@wwd   %% wedge top drop
\newdimen\tikzphysics@surface@wblx  %% resolved wedge bottom-left x
\newdimen\tikzphysics@surface@wbrx  %% resolved wedge bottom-right x
\newdimen\tikzphysics@surface@wrx   %% wedge wall-root x
\newdimen\tikzphysics@surface@wry   %% wedge wall-root y

%% 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. With zero inset/drop and the default wall angle
%% (-90 deg), wA/wB sit on y=+hy and wC/wD on y=-hy. A nonzero inset/drop
%% inserts the continuous straight segment from the floor tip to wA.
\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}
\def\tikzphysics@surface@wallinset{0cm}
\def\tikzphysics@surface@leftwallinset{0cm}
\def\tikzphysics@surface@rightwallinset{0cm}
\def\tikzphysics@surface@walldrop{0cm}
\def\tikzphysics@surface@leftwalldrop{0cm}
\def\tikzphysics@surface@rightwalldrop{0cm}
\def\tikzphysics@surface@wedgetopinset{0cm}
\def\tikzphysics@surface@wedgetopdrop{0cm}

%% ---- 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. The fixed floor
%%  corner IC is the end of the horizontal contact surface. The wall begins
%%  at A after an optional inward/downward transition from IC.
%%  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}[4]{%
  \tikzphysics@resolve@nonnegative{\tikzphysics@surface@wi}{#3}%
  \tikzphysics@resolve@nonnegative{\tikzphysics@surface@wd}{#4}%
  \ifdim\tikzphysics@surface@wi<\tikzphysics@surface@dx\relax\else
    \PackageError{tikzphysics}{wall inset must be smaller than platform width}%
      {Reduce wall inset or increase platform width.}%
  \fi
  %% An inward/downward transition belongs to a wall extending below the
  %% floor. On an upward wall it can make the outline cross the floor top.
  \pgfmathsetmacro{\tikzphysics@surface@@s}{sin(#2)}%
  \ifdim\tikzphysics@surface@@s pt>0.0001pt\relax
    \ifdim\dimexpr\tikzphysics@surface@wi+\tikzphysics@surface@wd\relax>0pt\relax
      \PackageError{tikzphysics}{upward wall cannot use wall inset or wall drop}%
        {Set wall inset=0 and wall drop=0 for an upward wall, or use a downward wall angle.}%
    \fi
  \fi
  \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)}%
  %% IC is the fixed floor tip. A is the wall root after the transition.
  %% The wall's inward normal is n=(-sin(theta),cos(theta)).
  \tikzphysics@surface@ICx=-\tikzphysics@surface@hx
  \tikzphysics@surface@ICy= \tikzphysics@surface@hy
  \tikzphysics@surface@wAx=\dimexpr\tikzphysics@surface@ICx+\tikzphysics@surface@wi\relax
  \tikzphysics@surface@wAy=\dimexpr\tikzphysics@surface@ICy-\tikzphysics@surface@wd\relax
  %% 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@wi=0pt\relax
      \ifdim\tikzphysics@surface@wd=0pt\relax\else
        \PackageError{tikzphysics}{wall drop needs a non-horizontal wall angle}%
          {Use a non-horizontal wall angle, or set wall drop=0.}%
      \fi
    \else
      \PackageError{tikzphysics}{wall inset needs a non-horizontal wall angle}%
        {Use a non-horizontal wall angle, or set wall inset=0.}%
    \fi
    \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*\tikzphysics@surface@@s
       +\tikzphysics@surface@@c*(\tikzphysics@surface@wd-\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)}%
  %% IC is the fixed floor tip. A is the wall root after the transition.
  %% The wall's inward normal is n=(sin(theta),-cos(theta)).
  \tikzphysics@surface@ICx=\tikzphysics@surface@hx
  \tikzphysics@surface@ICy=\tikzphysics@surface@hy
  \tikzphysics@surface@wAx=\dimexpr\tikzphysics@surface@ICx-\tikzphysics@surface@wi\relax
  \tikzphysics@surface@wAy=\dimexpr\tikzphysics@surface@ICy-\tikzphysics@surface@wd\relax
  %% 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@wi=0pt\relax
      \ifdim\tikzphysics@surface@wd=0pt\relax\else
        \PackageError{tikzphysics}{wall drop needs a non-horizontal wall angle}%
          {Use a non-horizontal wall angle, or set wall drop=0.}%
      \fi
    \else
      \PackageError{tikzphysics}{wall inset needs a non-horizontal wall angle}%
        {Use a non-horizontal wall angle, or set wall inset=0.}%
    \fi
    \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*\tikzphysics@surface@@s
       +\tikzphysics@surface@@c*(\tikzphysics@surface@wd-\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}%
    {\tikzphysics@surface@wallinset}{\tikzphysics@surface@walldrop}%
}

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

%% physicsplatformboth: two walls.  Left wall IC goes into ICx/ICy,
%% right wall IC goes into rICx/rICy.
\newcommand{\tikzphysics@surface@setpbdims}{%
  \tikzphysics@surface@setplatformdims
  \tikzphysics@resolve@nonnegative{\@tempdima}{\tikzphysics@surface@leftwallinset}%
  \tikzphysics@resolve@nonnegative{\@tempdimb}{\tikzphysics@surface@rightwallinset}%
  \advance\@tempdima by \@tempdimb\relax
  \ifdim\@tempdima<\tikzphysics@surface@dx\relax\else
    \PackageError{tikzphysics}{left and right wall insets must fit within platform width}%
      {Reduce either inset or increase platform width.}%
  \fi
  %% Left wall
  \tikzphysics@surface@setwall{left}{\tikzphysics@surface@leftwallangle}%
    {\tikzphysics@surface@leftwallinset}{\tikzphysics@surface@leftwalldrop}%
  %% 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}%
    {\tikzphysics@surface@rightwallinset}{\tikzphysics@surface@rightwalldrop}%
  %% 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)}%
}

%% Resolve the optional pulley-supporting nose on the side adjacent to the
%% bottom right-angle vertex.  The original apex remains fixed and therefore
%% remains the pulley centre.  The base corner moves inward to sit directly
%% below the wall root, giving one continuous four-point wedge body.
\def\tikzphysics@surface@setwedgeedge@br{%
  \ifdim\tikzphysics@surface@wwi=0pt\relax\else
    \pgfmathsetlength{\@tempdima}%
      {\tikzphysics@surface@wwi*tan(\tikzphysics@surface@ang)}%
    \ifdim\tikzphysics@surface@wwd>\@tempdima\relax\else
      \PackageError{tikzphysics}{wedge wall root must lie below the incline}%
        {Increase wedge top drop or reduce wedge top inset.}%
    \fi
  \fi
  \tikzphysics@surface@wbrx=\dimexpr\tikzphysics@surface@tx-\tikzphysics@surface@wwi\relax
  \tikzphysics@surface@wrx=\tikzphysics@surface@wbrx
  \tikzphysics@surface@wry=\dimexpr\tikzphysics@surface@hy-\tikzphysics@surface@wwd\relax
}
\def\tikzphysics@surface@setwedgeedge@bl{%
  \ifdim\tikzphysics@surface@wwi=0pt\relax\else
    \pgfmathsetlength{\@tempdima}%
      {\tikzphysics@surface@wwi*tan(\tikzphysics@surface@ang)}%
    \ifdim\tikzphysics@surface@wwd>\@tempdima\relax\else
      \PackageError{tikzphysics}{wedge wall root must lie below the incline}%
        {Increase wedge top drop or reduce wedge top inset.}%
    \fi
  \fi
  \tikzphysics@surface@wblx=\dimexpr\tikzphysics@surface@tx+\tikzphysics@surface@wwi\relax
  \tikzphysics@surface@wrx=\tikzphysics@surface@wblx
  \tikzphysics@surface@wry=\dimexpr\tikzphysics@surface@hy-\tikzphysics@surface@wwd\relax
}
\def\tikzphysics@surface@setwedgeedge@top{%
  \ifdim\tikzphysics@surface@wwi=0pt\relax
    \ifdim\tikzphysics@surface@wwd=0pt\relax\else
      \PackageError{tikzphysics}{wedge pulley edge is unavailable with right angle at=top}%
        {Use right angle at=br or bl, or set wedge top inset and wedge top drop to zero.}%
    \fi
  \else
    \PackageError{tikzphysics}{wedge pulley edge is unavailable with right angle at=top}%
      {Use right angle at=br or bl, or set wedge top inset and wedge top drop to zero.}%
  \fi
}

%% 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
  \tikzphysics@resolve@nonnegative{\tikzphysics@surface@wwi}{\tikzphysics@surface@wedgetopinset}%
  \tikzphysics@resolve@nonnegative{\tikzphysics@surface@wwd}{\tikzphysics@surface@wedgetopdrop}%
  \ifdim\tikzphysics@surface@wwi<\tikzphysics@surface@dx\relax\else
    \PackageError{tikzphysics}{wedge top inset must be smaller than wedge width}%
      {Reduce wedge top inset or increase wedge width.}%
  \fi
  \ifdim\tikzphysics@surface@wwd<\tikzphysics@surface@dy\relax\else
    \PackageError{tikzphysics}{wedge top drop must be smaller than wedge height}%
      {Reduce wedge top drop or increase wedge height.}%
  \fi
  \tikzphysics@surface@wblx=-\tikzphysics@surface@hx
  \tikzphysics@surface@wbrx=\tikzphysics@surface@hx
  \tikzphysics@surface@wrx=\tikzphysics@surface@tx
  \tikzphysics@surface@wry=\tikzphysics@surface@hy
  \csname tikzphysics@surface@setwedgeedge@\tikzphysics@surface@wedgeraq\endcsname
}

%% ============================================================
%%  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}},
  %% Optional tapered transition between a floor tip and its wall root.
  %% Shared forms set both sides; platform-left/right simply use the one
  %% relevant side. Zero values preserve the original sharp corner.
  physics wall inset/.code = {%
    \def\tikzphysics@surface@wallinset{#1}%
    \def\tikzphysics@surface@leftwallinset{#1}%
    \def\tikzphysics@surface@rightwallinset{#1}%
  },
  physics left wall inset/.code  = {\def\tikzphysics@surface@leftwallinset{#1}},
  physics right wall inset/.code = {\def\tikzphysics@surface@rightwallinset{#1}},
  physics wall drop/.code = {%
    \def\tikzphysics@surface@walldrop{#1}%
    \def\tikzphysics@surface@leftwalldrop{#1}%
    \def\tikzphysics@surface@rightwalldrop{#1}%
  },
  physics left wall drop/.code  = {\def\tikzphysics@surface@leftwalldrop{#1}},
  physics right wall drop/.code = {\def\tikzphysics@surface@rightwalldrop{#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}},
  wall inset/.style       = {physics wall inset={#1}},
  left wall inset/.style  = {physics left wall inset={#1}},
  right wall inset/.style = {physics right wall inset={#1}},
  wall drop/.style        = {physics wall drop={#1}},
  left wall drop/.style   = {physics left wall drop={#1}},
  right wall drop/.style  = {physics right wall drop={#1}},
  %% The platform preset uses a compact half-diameter transition.  Wedges
  %% retain the same 5 mm horizontal clearance with a longer 10 mm drop.
  physics pulley edge/.style={
    physics wall inset=0.5cm,
    physics wall drop=0.5cm,
    physics wedge top inset=0.5cm,
    physics wedge top drop=1cm
  },
  physics left pulley edge/.style={physics left wall inset=0.5cm, physics left wall drop=0.5cm},
  physics right pulley edge/.style={physics right wall inset=0.5cm, physics right wall drop=0.5cm},
  pulley edge/.style={physics pulley edge},
  pulley edges/.style={physics pulley edge},
  left pulley edge/.style={physics left pulley edge},
  right pulley edge/.style={physics right pulley edge},
  %% ---- 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}},
  physics wedge top inset/.code = {\def\tikzphysics@surface@wedgetopinset{#1}},
  physics wedge top drop/.code  = {\def\tikzphysics@surface@wedgetopdrop{#1}},
  %% 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}},
  wedge top inset/.style      = {physics wedge top inset={#1}},
  wedge top drop/.style       = {physics wedge top drop={#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 (starts after the optional transition):
%%    projecting floor tip = (-hx, hy)
%%    wall root A = (-hx+wall inset, hy-wall drop)
%%    default (wall angle = -90): wall lies in
%%      a vertical strip extending from A
%%    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@ICx}{\tikzphysics@surface@pl@ICy}}%
    \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 -> wall root -> floor tip
  %% -> opposite 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@ICx}{\tikzphysics@surface@pl@ICy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}}%
    \pgfusepath{stroke}%
  }

  %% Contact midpoint and semantic points; all boundary corners and midpoints
  %% are available as 0, 50, and 100 of their percentage families.
  \anchor{surface}{\pgf@x=0pt \pgf@y=\tikzphysics@surface@pl@hy}
  \anchor{pulley-center}{\pgf@x=\tikzphysics@surface@pl@ICx \pgf@y=\tikzphysics@surface@pl@ICy}
  \anchor{wall-root}{\pgf@x=\tikzphysics@surface@pl@wAx \pgf@y=\tikzphysics@surface@pl@wAy}
  \anchor{floor-center}{\pgf@x=0pt
    \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pl@hy-0.5*\tikzphysics@surface@pl@sw}}
  \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}}

  %% Floor: horizontal edges run left to right; sides run bottom to top.
  \tikzphysics@declareedgeanchors{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{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{surface}
    {-\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}
    {\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}
  \tikzphysics@declareedgeanchors{left}
    {-\tikzphysics@surface@pl@hx}{\dimexpr\tikzphysics@surface@pl@hy-\tikzphysics@surface@pl@sw\relax}
    {-\tikzphysics@surface@pl@hx}{\tikzphysics@surface@pl@hy}

  %% Transition runs from the projecting floor tip to the wall root.
  \tikzphysics@declareedgeanchors{transition}
    {\tikzphysics@surface@pl@ICx}{\tikzphysics@surface@pl@ICy}
    {\tikzphysics@surface@pl@wAx}{\tikzphysics@surface@pl@wAy}

  %% Wall: long faces run root to tip; short faces run outer to inner.
  \tikzphysics@declareedgeanchors{wall-surface}
    {\tikzphysics@surface@pl@wAx}{\tikzphysics@surface@pl@wAy}
    {\tikzphysics@surface@pl@wDx}{\tikzphysics@surface@pl@wDy}
  \tikzphysics@declareedgeanchors{wall-back}
    {\tikzphysics@surface@pl@wBx}{\tikzphysics@surface@pl@wBy}
    {\tikzphysics@surface@pl@wCx}{\tikzphysics@surface@pl@wCy}
  \tikzphysics@declareedgeanchors{wall-base}
    {\tikzphysics@surface@pl@wAx}{\tikzphysics@surface@pl@wAy}
    {\tikzphysics@surface@pl@wBx}{\tikzphysics@surface@pl@wBy}
  \tikzphysics@declareedgeanchors{wall-tip}
    {\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. The projecting floor tip is (+hx, hy); the wall
%%  begins at the optional inward/downward wall root. 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@ICx}{\tikzphysics@surface@pr@ICy}}%
    \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 -> floor tip -> wall root
  %% -> wall free end.
  \foregroundpath{%
    \pgfsetlinewidth{0.5pt}%
    \pgfpathmoveto{\pgfpoint{-\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pr@ICx}{\tikzphysics@surface@pr@ICy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pr@wAx}{\tikzphysics@surface@pr@wAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pr@wDx}{\tikzphysics@surface@pr@wDy}}%
    \pgfusepath{stroke}%
  }

  %% Contact midpoint and semantic points; all boundary corners and midpoints
  %% are available as 0, 50, and 100 of their percentage families.
  \anchor{surface}{\pgf@x=0pt \pgf@y=\tikzphysics@surface@pr@hy}
  \anchor{pulley-center}{\pgf@x=\tikzphysics@surface@pr@ICx \pgf@y=\tikzphysics@surface@pr@ICy}
  \anchor{wall-root}{\pgf@x=\tikzphysics@surface@pr@wAx \pgf@y=\tikzphysics@surface@pr@wAy}
  \anchor{floor-center}{\pgf@x=0pt
    \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pr@hy-0.5*\tikzphysics@surface@pr@sw}}
  \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}}

  %% Floor: horizontal edges run left to right; sides run bottom to top.
  \tikzphysics@declareedgeanchors{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{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{surface}
    {-\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}
    {\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}
  \tikzphysics@declareedgeanchors{left}
    {-\tikzphysics@surface@pr@hx}{\dimexpr\tikzphysics@surface@pr@hy-\tikzphysics@surface@pr@sw\relax}
    {-\tikzphysics@surface@pr@hx}{\tikzphysics@surface@pr@hy}

  %% Transition runs from the projecting floor tip to the wall root.
  \tikzphysics@declareedgeanchors{transition}
    {\tikzphysics@surface@pr@ICx}{\tikzphysics@surface@pr@ICy}
    {\tikzphysics@surface@pr@wAx}{\tikzphysics@surface@pr@wAy}

  %% Wall: long faces run root to tip; short faces run outer to inner.
  \tikzphysics@declareedgeanchors{wall-surface}
    {\tikzphysics@surface@pr@wAx}{\tikzphysics@surface@pr@wAy}
    {\tikzphysics@surface@pr@wDx}{\tikzphysics@surface@pr@wDy}
  \tikzphysics@declareedgeanchors{wall-back}
    {\tikzphysics@surface@pr@wBx}{\tikzphysics@surface@pr@wBy}
    {\tikzphysics@surface@pr@wCx}{\tikzphysics@surface@pr@wCy}
  \tikzphysics@declareedgeanchors{wall-base}
    {\tikzphysics@surface@pr@wAx}{\tikzphysics@surface@pr@wAy}
    {\tikzphysics@surface@pr@wBx}{\tikzphysics@surface@pr@wBy}
  \tikzphysics@declareedgeanchors{wall-tip}
    {\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@lICx}{\tikzphysics@surface@pb@lICy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rICx}{\tikzphysics@surface@pb@rICy}}%
    \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@lICx}{\tikzphysics@surface@pb@lICy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rICx}{\tikzphysics@surface@pb@rICy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rAx}{\tikzphysics@surface@pb@rAy}}%
    \pgfpathlineto{\pgfpoint{\tikzphysics@surface@pb@rDx}{\tikzphysics@surface@pb@rDy}}%
    \pgfusepath{stroke}%
  }

  %% Contact midpoint and semantic points; percentage endpoints cover corners.
  \anchor{surface}{\pgf@x=0pt \pgf@y=\tikzphysics@surface@pb@hy}
  \anchor{left-pulley-center}{\pgf@x=\tikzphysics@surface@pb@lICx \pgf@y=\tikzphysics@surface@pb@lICy}
  \anchor{right-pulley-center}{\pgf@x=\tikzphysics@surface@pb@rICx \pgf@y=\tikzphysics@surface@pb@rICy}
  \anchor{left-wall-root}{\pgf@x=\tikzphysics@surface@pb@lAx \pgf@y=\tikzphysics@surface@pb@lAy}
  \anchor{right-wall-root}{\pgf@x=\tikzphysics@surface@pb@rAx \pgf@y=\tikzphysics@surface@pb@rAy}
  \anchor{floor-center}{\pgf@x=0pt
    \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@pb@hy-0.5*\tikzphysics@surface@pb@sw}}
  \anchor{left-wall-center}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@lAx+\tikzphysics@surface@pb@lBx+\tikzphysics@surface@pb@lCx+\tikzphysics@surface@pb@lDx)/4}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@lAy+\tikzphysics@surface@pb@lBy+\tikzphysics@surface@pb@lCy+\tikzphysics@surface@pb@lDy)/4}}
  \anchor{right-wall-center}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@pb@rAx+\tikzphysics@surface@pb@rBx+\tikzphysics@surface@pb@rCx+\tikzphysics@surface@pb@rDx)/4}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@pb@rAy+\tikzphysics@surface@pb@rBy+\tikzphysics@surface@pb@rCy+\tikzphysics@surface@pb@rDy)/4}}

  %% Floor: horizontal edges run left to right; sides run bottom to top.
  \tikzphysics@declareedgeanchors{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{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{surface}
    {-\tikzphysics@surface@pb@hx}{\tikzphysics@surface@pb@hy}
    {\tikzphysics@surface@pb@hx}{\tikzphysics@surface@pb@hy}
  \tikzphysics@declareedgeanchors{left}
    {-\tikzphysics@surface@pb@hx}{\dimexpr\tikzphysics@surface@pb@hy-\tikzphysics@surface@pb@sw\relax}
    {-\tikzphysics@surface@pb@hx}{\tikzphysics@surface@pb@hy}

  \tikzphysics@declareedgeanchors{left-transition}
    {\tikzphysics@surface@pb@lICx}{\tikzphysics@surface@pb@lICy}
    {\tikzphysics@surface@pb@lAx}{\tikzphysics@surface@pb@lAy}
  \tikzphysics@declareedgeanchors{right-transition}
    {\tikzphysics@surface@pb@rICx}{\tikzphysics@surface@pb@rICy}
    {\tikzphysics@surface@pb@rAx}{\tikzphysics@surface@pb@rAy}

  %% Left wall: long faces root to tip; short faces outer to inner.
  \tikzphysics@declareedgeanchors{left-wall-surface}
    {\tikzphysics@surface@pb@lAx}{\tikzphysics@surface@pb@lAy}
    {\tikzphysics@surface@pb@lDx}{\tikzphysics@surface@pb@lDy}
  \tikzphysics@declareedgeanchors{left-wall-back}
    {\tikzphysics@surface@pb@lBx}{\tikzphysics@surface@pb@lBy}
    {\tikzphysics@surface@pb@lCx}{\tikzphysics@surface@pb@lCy}
  \tikzphysics@declareedgeanchors{left-wall-base}
    {\tikzphysics@surface@pb@lAx}{\tikzphysics@surface@pb@lAy}
    {\tikzphysics@surface@pb@lBx}{\tikzphysics@surface@pb@lBy}
  \tikzphysics@declareedgeanchors{left-wall-tip}
    {\tikzphysics@surface@pb@lDx}{\tikzphysics@surface@pb@lDy}
    {\tikzphysics@surface@pb@lCx}{\tikzphysics@surface@pb@lCy}

  %% Right wall: long faces root to tip; short faces outer to inner.
  \tikzphysics@declareedgeanchors{right-wall-surface}
    {\tikzphysics@surface@pb@rAx}{\tikzphysics@surface@pb@rAy}
    {\tikzphysics@surface@pb@rDx}{\tikzphysics@surface@pb@rDy}
  \tikzphysics@declareedgeanchors{right-wall-back}
    {\tikzphysics@surface@pb@rBx}{\tikzphysics@surface@pb@rBy}
    {\tikzphysics@surface@pb@rCx}{\tikzphysics@surface@pb@rCy}
  \tikzphysics@declareedgeanchors{right-wall-base}
    {\tikzphysics@surface@pb@rAx}{\tikzphysics@surface@pb@rAy}
    {\tikzphysics@surface@pb@rBx}{\tikzphysics@surface@pb@rBy}
  \tikzphysics@declareedgeanchors{right-wall-tip}
    {\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
  }%
}

%% Point on a two-segment polyline, parameterised by actual path length.
%% The first segment is always non-degenerate for a valid wedge.  The
%% zero-inset/zero-drop case bypasses this helper in the edge dispatchers.
\def\tikzphysics@surface@wedgepolylinepoint#1#2#3#4#5#6#7{%
  \pgfmathsetmacro{\tikzphysics@surface@w@lenA}%
    {veclen((#4)-(#2),(#5)-(#3))}%
  \pgfmathsetmacro{\tikzphysics@surface@w@lenB}%
    {veclen((#6)-(#4),(#7)-(#5))}%
  \pgfmathsetmacro{\tikzphysics@surface@w@target}%
    {(#1/100)*(\tikzphysics@surface@w@lenA+\tikzphysics@surface@w@lenB)}%
  \ifdim\tikzphysics@surface@w@target pt<\tikzphysics@surface@w@lenA pt\relax
    \pgfmathsetmacro{\tikzphysics@surface@w@fraction}%
      {\tikzphysics@surface@w@target/\tikzphysics@surface@w@lenA}%
    \pgfmathsetlength{\pgf@x}{(#2)+\tikzphysics@surface@w@fraction*((#4)-(#2))}%
    \pgfmathsetlength{\pgf@y}{(#3)+\tikzphysics@surface@w@fraction*((#5)-(#3))}%
  \else
    \pgfmathsetmacro{\tikzphysics@surface@w@fraction}%
      {(\tikzphysics@surface@w@target-\tikzphysics@surface@w@lenA)/
       \tikzphysics@surface@w@lenB}%
    \pgfmathsetlength{\pgf@x}{(#4)+\tikzphysics@surface@w@fraction*((#6)-(#4))}%
    \pgfmathsetlength{\pgf@y}{(#5)+\tikzphysics@surface@w@fraction*((#7)-(#5))}%
  \fi
}

\def\tikzphysics@surface@wedgerightpoint#1{%
  \csname tikzphysics@surface@wedgerightpoint@\tikzphysics@surface@w@ra\endcsname{#1}%
}
\def\tikzphysics@surface@wedgerightpoint@br#1{%
  \ifdim\tikzphysics@surface@w@wi=0pt\relax
    \ifdim\tikzphysics@surface@w@wd=0pt\relax
      \pgfmathsetlength{\pgf@x}{\tikzphysics@surface@w@brx+(#1/100)*
        (\tikzphysics@surface@w@tx-\tikzphysics@surface@w@brx)}%
      \pgfmathsetlength{\pgf@y}{-\tikzphysics@surface@w@hy+(#1/100)*
        (2*\tikzphysics@surface@w@hy)}%
    \else
      \tikzphysics@surface@wedgepolylinepoint{#1}%
        {\tikzphysics@surface@w@brx}{-\tikzphysics@surface@w@hy}%
        {\tikzphysics@surface@w@rootx}{\tikzphysics@surface@w@rooty}%
        {\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}%
    \fi
  \else
    \tikzphysics@surface@wedgepolylinepoint{#1}%
      {\tikzphysics@surface@w@brx}{-\tikzphysics@surface@w@hy}%
      {\tikzphysics@surface@w@rootx}{\tikzphysics@surface@w@rooty}%
      {\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}%
  \fi
}
\def\tikzphysics@surface@wedgerightpoint@bl#1{%
  \pgfmathsetlength{\pgf@x}{\tikzphysics@surface@w@brx+(#1/100)*
    (\tikzphysics@surface@w@tx-\tikzphysics@surface@w@brx)}%
  \pgfmathsetlength{\pgf@y}{-\tikzphysics@surface@w@hy+(#1/100)*
    (2*\tikzphysics@surface@w@hy)}%
}
\let\tikzphysics@surface@wedgerightpoint@top\tikzphysics@surface@wedgerightpoint@bl

\def\tikzphysics@surface@wedgeslopepoint#1{%
  \csname tikzphysics@surface@wedgeslopepoint@\tikzphysics@surface@w@ra\endcsname{#1}%
}
\def\tikzphysics@surface@wedgeslopepoint@br#1{%
  \pgfmathsetlength{\pgf@x}{\tikzphysics@surface@w@tx+(#1/100)*
    (\tikzphysics@surface@w@blx-\tikzphysics@surface@w@tx)}%
  \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@w@hy-(#1/100)*
    (2*\tikzphysics@surface@w@hy)}%
}
\let\tikzphysics@surface@wedgeslopepoint@top\tikzphysics@surface@wedgeslopepoint@br
\def\tikzphysics@surface@wedgeslopepoint@bl#1{%
  \ifdim\tikzphysics@surface@w@wi=0pt\relax
    \ifdim\tikzphysics@surface@w@wd=0pt\relax
      \pgfmathsetlength{\pgf@x}{\tikzphysics@surface@w@tx+(#1/100)*
        (\tikzphysics@surface@w@blx-\tikzphysics@surface@w@tx)}%
      \pgfmathsetlength{\pgf@y}{\tikzphysics@surface@w@hy-(#1/100)*
        (2*\tikzphysics@surface@w@hy)}%
    \else
      \tikzphysics@surface@wedgepolylinepoint{#1}%
        {\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}%
        {\tikzphysics@surface@w@rootx}{\tikzphysics@surface@w@rooty}%
        {\tikzphysics@surface@w@blx}{-\tikzphysics@surface@w@hy}%
    \fi
  \else
    \tikzphysics@surface@wedgepolylinepoint{#1}%
      {\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}%
      {\tikzphysics@surface@w@rootx}{\tikzphysics@surface@w@rooty}%
      {\tikzphysics@surface@w@blx}{-\tikzphysics@surface@w@hy}%
  \fi
}

\def\tikzphysics@surface@declarewedgeboundary@one#1#2{%
  \anchor{#1-#2}{\csname tikzphysics@surface@wedge#1point\endcsname{#2}}%
}
\def\tikzphysics@surface@declarewedgeboundaryanchors#1{%
  \foreach \tikzphysics@@t in {0,1,...,100}{%
    \edef\tikzphysics@@partial{%
      \noexpand\tikzphysics@surface@declarewedgeboundary@one{#1}{\tikzphysics@@t}}%
    \tikzphysics@@partial
  }%
}

\def\tikzphysics@surface@wedgepath@br{%
  \pgfpathmoveto{\pgfpoint{\tikzphysics@surface@w@blx}{-\tikzphysics@surface@w@hy}}%
  \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@brx}{-\tikzphysics@surface@w@hy}}%
  \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@rootx}{\tikzphysics@surface@w@rooty}}%
  \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}}%
  \pgfpathclose
}
\def\tikzphysics@surface@wedgepath@bl{%
  \pgfpathmoveto{\pgfpoint{\tikzphysics@surface@w@blx}{-\tikzphysics@surface@w@hy}}%
  \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@brx}{-\tikzphysics@surface@w@hy}}%
  \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}}%
  \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@rootx}{\tikzphysics@surface@w@rooty}}%
  \pgfpathclose
}
\def\tikzphysics@surface@wedgepath@top{%
  \pgfpathmoveto{\pgfpoint{\tikzphysics@surface@w@blx}{-\tikzphysics@surface@w@hy}}%
  \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@brx}{-\tikzphysics@surface@w@hy}}%
  \pgfpathlineto{\pgfpoint{\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}}%
  \pgfpathclose
}

%% Area centroid of the visible polygon.  Without a pulley edge its fourth
%% vertex coincides with top, so the same formula gives the triangle centroid.
%% Work in centimetres to keep PGF's fixed-point products small.
\def\tikzphysics@surface@wedgecentroid{%
  \pgfmathsetmacro{\tikzphysics@surface@c@ax}{\tikzphysics@surface@w@blx/1cm}%
  \pgfmathsetmacro{\tikzphysics@surface@c@bx}{\tikzphysics@surface@w@brx/1cm}%
  \pgfmathsetmacro{\tikzphysics@surface@c@ay}{-\tikzphysics@surface@w@hy/1cm}%
  \pgfmathsetmacro{\tikzphysics@surface@c@tx}{\tikzphysics@surface@w@tx/1cm}%
  \pgfmathsetmacro{\tikzphysics@surface@c@ty}{\tikzphysics@surface@w@hy/1cm}%
  \pgfmathsetmacro{\tikzphysics@surface@c@rx}{\tikzphysics@surface@w@rootx/1cm}%
  \pgfmathsetmacro{\tikzphysics@surface@c@ry}{\tikzphysics@surface@w@rooty/1cm}%
  \def\tikzphysics@surface@c@bl{bl}%
  \ifx\tikzphysics@surface@w@ra\tikzphysics@surface@c@bl
    \let\tikzphysics@surface@c@cx\tikzphysics@surface@c@tx
    \let\tikzphysics@surface@c@cy\tikzphysics@surface@c@ty
    \let\tikzphysics@surface@c@dx\tikzphysics@surface@c@rx
    \let\tikzphysics@surface@c@dy\tikzphysics@surface@c@ry
  \else
    \let\tikzphysics@surface@c@cx\tikzphysics@surface@c@rx
    \let\tikzphysics@surface@c@cy\tikzphysics@surface@c@ry
    \let\tikzphysics@surface@c@dx\tikzphysics@surface@c@tx
    \let\tikzphysics@surface@c@dy\tikzphysics@surface@c@ty
  \fi
  \pgfmathsetmacro{\tikzphysics@surface@c@areaone}%
    {(\tikzphysics@surface@c@bx-\tikzphysics@surface@c@ax)*
     (\tikzphysics@surface@c@cy-\tikzphysics@surface@c@ay)}%
  \pgfmathsetmacro{\tikzphysics@surface@c@areatwo}%
    {(\tikzphysics@surface@c@cx-\tikzphysics@surface@c@ax)*
     (\tikzphysics@surface@c@dy-\tikzphysics@surface@c@ay)-
     (\tikzphysics@surface@c@cy-\tikzphysics@surface@c@ay)*
     (\tikzphysics@surface@c@dx-\tikzphysics@surface@c@ax)}%
  \pgfmathsetlength{\pgf@x}{
    ((\tikzphysics@surface@c@ax+\tikzphysics@surface@c@bx+\tikzphysics@surface@c@cx)*
       \tikzphysics@surface@c@areaone+
     (\tikzphysics@surface@c@ax+\tikzphysics@surface@c@cx+\tikzphysics@surface@c@dx)*
       \tikzphysics@surface@c@areatwo)/
    (3*(\tikzphysics@surface@c@areaone+\tikzphysics@surface@c@areatwo))*1cm}%
  \pgfmathsetlength{\pgf@y}{
    ((2*\tikzphysics@surface@c@ay+\tikzphysics@surface@c@cy)*
       \tikzphysics@surface@c@areaone+
     (\tikzphysics@surface@c@ay+\tikzphysics@surface@c@cy+\tikzphysics@surface@c@dy)*
       \tikzphysics@surface@c@areatwo)/
    (3*(\tikzphysics@surface@c@areaone+\tikzphysics@surface@c@areatwo))*1cm}%
}

\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}%
  }
  \savedmacro{\tikzphysics@surface@w@wi}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@wi{\the\tikzphysics@surface@wwi}%
  }
  \savedmacro{\tikzphysics@surface@w@wd}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@wd{\the\tikzphysics@surface@wwd}%
  }
  \savedmacro{\tikzphysics@surface@w@blx}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@blx{\the\tikzphysics@surface@wblx}%
  }
  \savedmacro{\tikzphysics@surface@w@brx}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@brx{\the\tikzphysics@surface@wbrx}%
  }
  \savedmacro{\tikzphysics@surface@w@rootx}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@rootx{\the\tikzphysics@surface@wrx}%
  }
  \savedmacro{\tikzphysics@surface@w@rooty}{%
    \tikzphysics@surface@setwedgedims
    \edef\tikzphysics@surface@w@rooty{\the\tikzphysics@surface@wry}%
  }

  %% ---- 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@blx \pgf@y=-\tikzphysics@surface@w@hy}
  \anchor{br}  {\pgf@x=\tikzphysics@surface@w@brx \pgf@y=-\tikzphysics@surface@w@hy}
  \anchor{top} {\pgf@x=\tikzphysics@surface@w@tx  \pgf@y=\tikzphysics@surface@w@hy}
  \anchor{pulley-center}{\pgf@x=\tikzphysics@surface@w@tx \pgf@y=\tikzphysics@surface@w@hy}
  \anchor{wall-root}{\pgf@x=\tikzphysics@surface@w@rootx \pgf@y=\tikzphysics@surface@w@rooty}
  \anchor{transition-mid}{%
    \pgfmathsetlength{\pgf@x}{(\tikzphysics@surface@w@tx+\tikzphysics@surface@w@rootx)/2}%
    \pgfmathsetlength{\pgf@y}{(\tikzphysics@surface@w@hy+\tikzphysics@surface@w@rooty)/2}%
  }

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

  %% Named midpoints use the same boundary/contact parameterisation as
  %% their percentage families.  In particular, right-50 follows the
  %% complete two-segment boundary when a pulley edge adds a nose.
  \anchor{right-mid}{\tikzphysics@surface@wedgerightpoint{50}}
  \anchor{slope-mid}{\tikzphysics@surface@contactpoint{50}{left}}

  %% In top mode the second usable slope is on the right.  The other
  %% modes have only one usable incline, so this equals slope-mid.
  \anchor{slope-right-mid}{%
    \def\tikzphysics@surface@ra@top{top}%
    \ifx\tikzphysics@surface@w@ra\tikzphysics@surface@ra@top
      \tikzphysics@surface@contactpoint{50}{right}%
    \else
      \tikzphysics@surface@contactpoint{50}{left}%
    \fi
  }

  \anchor{centroid}{\tikzphysics@surface@wedgecentroid}
  \anchor{mid}{\tikzphysics@surface@wedgecentroid}

  %% ---- background (fill/pattern) path ----
  %% Ordinary wedges remain triangles.  In br/bl mode a nonzero top inset
  %% or drop inserts wall-root between the right-angle base corner and top,
  %% producing one continuous four-point body.
  \backgroundpath{%
    \csname tikzphysics@surface@wedgepath@\tikzphysics@surface@w@ra\endcsname
  }

  %% ---- 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@blx}{-\tikzphysics@surface@w@hy}
    {\tikzphysics@surface@w@brx}{-\tikzphysics@surface@w@hy}
  \tikzphysics@surface@declarewedgeboundaryanchors{right}
  \tikzphysics@surface@declarewedgeboundaryanchors{slope}
  \tikzphysics@declareedgeanchors{transition}
    {\tikzphysics@surface@w@tx}{\tikzphysics@surface@w@hy}
    {\tikzphysics@surface@w@rootx}{\tikzphysics@surface@w@rooty}
}

%% 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
      \def\tikzphysics@surface@g@topmode{top}%
      \def\tikzphysics@surface@g@rootangle{180}%
      \ifx\tikzphysics@surface@g@mode\tikzphysics@surface@g@topmode\else
        \ifdim\tikzphysics@surface@w@wi=0pt\relax
          \ifdim\tikzphysics@surface@w@wd=0pt\relax\else
            \def\tikzphysics@surface@g@rootangle{180}%
          \fi
        \else
          \pgfmathsetmacro{\tikzphysics@surface@g@transitionangle}%
            {atan2(\tikzphysics@surface@w@wd,\tikzphysics@surface@w@wi)}%
          \pgfmathsetmacro{\tikzphysics@surface@g@topangle}%
            {\tikzphysics@surface@g@transitionangle-\tikzphysics@surface@g@inputangle}%
          \pgfmathsetmacro{\tikzphysics@surface@g@rootangle}%
            {270-\tikzphysics@surface@g@transitionangle}%
        \fi
      \fi
      \@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}{top inset}{\tikzphysics@surface@w@wi}%
      \tikzphysics@storegeometryvalue{#1}{top drop}{\tikzphysics@surface@w@wd}%
      \tikzphysics@storegeometryvalue{#1}{wall root angle}{\tikzphysics@surface@g@rootangle}%
      \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, center, and the usable face's midpoint (`surface').
%%  Each boundary has a percentage family; 50 is its midpoint.
%% ============================================================

\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{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{surface}{\pgf@x=0pt \pgf@y=\tikzphysics@surface@g@hy}

  %% Contact face is surface; horizontal edges left to right, vertical bottom to top. ----
  \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{surface}
    {-\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{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{surface}{\pgf@x=0pt \pgf@y=-\tikzphysics@surface@c@hy}

  %% Contact face is surface; horizontal edges left to right, vertical bottom to top. ----
  \tikzphysics@declareedgeanchors{surface}
    {-\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{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{surface}{\pgf@x=\tikzphysics@surface@wl@hx \pgf@y=0pt}

  %% Contact face is surface; horizontal edges left to right, vertical bottom to top. ----
  \tikzphysics@declareedgeanchors{bottom}
    {-\tikzphysics@surface@wl@hx}{-\tikzphysics@surface@wl@hy}
    {\tikzphysics@surface@wl@hx}{-\tikzphysics@surface@wl@hy}
  \tikzphysics@declareedgeanchors{surface}
    {\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{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{surface}{\pgf@x=-\tikzphysics@surface@wr@hx \pgf@y=0pt}

  %% Contact face is surface; horizontal edges left to right, vertical bottom to top. ----
  \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{surface}
    {-\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}{%
  surface, pulley-center, wall-root, floor-center, wall-center, center}
\tikzphysics@registeranchors{physicsplatformright}{%
  surface, pulley-center, wall-root, floor-center, wall-center, center}
\tikzphysics@registeranchors{physicsplatformboth}{%
  surface, left-pulley-center, right-pulley-center,
  left-wall-root, right-wall-root, floor-center,
  left-wall-center, right-wall-center, center}
\tikzphysics@registeranchors{physicswedge}{%
  bl, br, top, pulley-center, wall-root, transition-mid,
  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, bottom-left, bottom-right, surface, center}
\tikzphysics@registeranchors{physicsceiling}{%
  top-left, top-right, bottom-left, bottom-right, surface, center}
\tikzphysics@registeranchors{physicswallleft}{%
  top-left, top-right, bottom-left, bottom-right, surface, center}
\tikzphysics@registeranchors{physicswallright}{%
  top-left, top-right, bottom-left, bottom-right, 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,
  wall inset, wall drop, pulley edge}
\tikzphysics@registerkeydefaults{physicsplatformleft}{%
  minimum width/5cm, minimum height/2cm, strip width/0.25cm, wall angle/$-90^\circ$,
  wall inset/0cm, wall drop/0cm, pulley edge/off; preset uses 0.5cm inset and drop}
\tikzphysics@registerkeys{physicsplatformright}{%
  minimum width, minimum height, strip width, wall angle,
  wall inset, wall drop, pulley edge}
\tikzphysics@registerkeydefaults{physicsplatformright}{%
  minimum width/5cm, minimum height/2cm, strip width/0.25cm, wall angle/$-90^\circ$,
  wall inset/0cm, wall drop/0cm, pulley edge/off; preset uses 0.5cm inset and drop}
\tikzphysics@registerkeys{physicsplatformboth}{%
  minimum width, minimum height, strip width,
  wall angle, left wall angle, right wall angle,
  wall inset, left wall inset, right wall inset,
  wall drop, left wall drop, right wall drop,
  pulley edge, left pulley edge, right pulley edge, pulley edges}
\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$,
  wall inset/0cm, left wall inset/0cm, right wall inset/0cm,
  wall drop/0cm, left wall drop/0cm, right wall drop/0cm,
  pulley edge/off; shared preset uses 0.5cm inset and drop,
  left pulley edge/off; left-side preset uses 0.5cm inset and drop,
  right pulley edge/off; right-side preset uses 0.5cm inset and drop,
  pulley edges/off; both-side alias of pulley edge}
\tikzphysics@registerkeys{physicswedge}{%
  minimum width, wedge height, wedge angle, wedge right angle at,
  wedge top inset, wedge top drop, pulley edge}
\tikzphysics@registerkeydefaults{physicswedge}{%
  minimum width/4cm, wedge height/derived, wedge angle/$30^\circ$, wedge right angle at/br,
  wedge top inset/0cm, wedge top drop/0cm,
  pulley edge/off; preset uses 0.5cm inset and 1cm drop, 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=surface-0,
    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=surface-100,
    draw=none,
    fill=white,
    %% Mirror the left-side hatch so it crosses the tapered right edge and
    %% reads as material continuing inward from the projecting tip.
    pattern=north west 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=surface,
    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=surface,
    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=surface,
    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=surface,
    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=surface,
    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 wall inset/.value required,
  physics left wall inset/.value required,
  physics right wall inset/.value required,
  physics wall drop/.value required,
  physics left wall drop/.value required,
  physics right wall drop/.value required,
  physics wedge width/.value required,
  physics wedge height/.value required,
  physics wedge angle/.value required,
  physics wedge top inset/.value required,
  physics wedge top drop/.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'.
