< Summary

Information
Class: FixedMathSharp.Geometry.ScaledRigidFrame3d
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Common/ScaledRigidFrame3d.cs
Line coverage
100%
Covered lines: 244
Uncovered lines: 0
Coverable lines: 244
Total lines: 466
Line coverage: 100%
Branch coverage
100%
Covered branches: 90
Total branches: 90
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
get_IsRigid()100%11100%
get_RigidOrigin()100%11100%
get_Rotation()100%11100%
get_HasLocalPlacement()100%11100%
FixedMathSharp.Geometry.IForwardHullFrame3d.get_RotationDenominator()100%11100%
FixedMathSharp.Geometry.IForwardHullFrame3d.get_Denominator()100%11100%
FixedMathSharp.Geometry.IForwardHullFrame3d.GetPoint(...)100%11100%
FixedMathSharp.Geometry.IForwardHullFrame3d.GetFaceNormal(...)100%11100%
FixedMathSharp.Geometry.IForwardHullFrame3d.GetEdgeDirection(...)100%11100%
FixedMathSharp.Geometry.IForwardHullFrame3d.GetInwardAxis(...)100%11100%
FixedMathSharp.Geometry.IForwardHullFrame3d.TryGetTriangleHalfPlanes(...)100%11100%
Rigid(...)100%11100%
.ctor(...)100%2626100%
GetScaledLocalPointNumerators(...)100%11100%
GetPoint(...)100%44100%
TryGetPoint(...)100%11100%
GetScaledLocalPoint(...)100%22100%
TryGetScaledLocalPointIn(...)100%22100%
IsScaledLocalPointExact(...)100%11100%
GetSourceDirectionNumerators(...)100%11100%
GetWorldDirectionNumerators(...)100%22100%
GetWorldBounds(...)100%44100%
TryGetSourceBounds(...)100%88100%
TryGetBoundsIn(...)100%1010100%
GetSourcePointNumerators(...)100%11100%
TryGetSourceBoundsFromScaledLocal(...)100%1212100%
HasSameMapping(...)100%88100%
GetSourceCoordinateTransform(...)100%11100%
GetScale(...)100%44100%
SameLinearCoordinate(...)100%11100%
SameMappedCoordinate(...)100%11100%
GetCorner(...)100%66100%
RemoveScaleDenominator(...)100%11100%
IncludeBound(...)100%11100%
ScaleReference(...)100%11100%
GetScaledLocalPointNumeratorsIn(...)100%11100%
GetSourceCoordinate(...)100%11100%
GetTranslation(...)100%22100%
GetWorldCoordinate(...)100%11100%
GetScaledDifference(...)100%11100%
GetOrdinaryCoordinate(...)100%11100%
Rotate(...)100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Common/ScaledRigidFrame3d.cs

#LineLine coverage
 1//=======================================================================
 2// ScaledRigidFrame3d.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9
 10namespace FixedMathSharp.Geometry;
 11
 12/// <summary>
 13/// Retains scaled source points and a separately rotated placement without
 14/// rounding either scale products, reference subtraction, or frame origins.
 15/// </summary>
 16/// <remarks>
 17/// The exact point is T + Rp(offset * ownerScale) +
 18/// Rg((source - reference) * ownerScale * partScale). Scale factors may be
 19/// signed or zero; rotations must be normalized. All inputs use their complete
 20/// scalar domains. Only final Q32.32 materialization can fail representability.
 21/// </remarks>
 22internal readonly struct ScaledRigidFrame3d : IForwardHullFrame3d
 23{
 124    private static readonly Signed192 ScaleDenominator = new(0UL, 1UL, 0UL);
 25    private readonly Vector3d _reference;
 26    private readonly Vector3d _translation;
 27    private readonly Signed192 _scaleX, _scaleY, _scaleZ;
 28    private readonly Signed192 _offsetX, _offsetY, _offsetZ;
 29    private readonly Signed320 _translationX, _translationY, _translationZ;
 30    private readonly Signed192 _placementDenominator;
 31    private readonly bool _sameRotation, _identityUnit, _isRigid;
 32
 33    internal readonly WideRationalBasis3d GeometryBasis;
 34    internal readonly FixedQuaternion GeometryRotation;
 35    internal readonly Signed192 RotationDenominator;
 36    internal readonly Signed320 Denominator;
 37
 15868838    internal bool IsRigid => _isRigid;
 39
 65140    internal Vector3d RigidOrigin => _translation;
 61641    internal FixedQuaternion Rotation => GeometryRotation;
 242    internal bool HasLocalPlacement => !(_offsetX.IsZero & _offsetY.IsZero & _offsetZ.IsZero);
 43
 1112744    Signed192 IForwardHullFrame3d.RotationDenominator => RotationDenominator;
 55645    Signed320 IForwardHullFrame3d.Denominator => Denominator;
 10094046    RationalPoint3d IForwardHullFrame3d.GetPoint(Vector3d point) => GetPoint(point);
 47    WideDirection3d IForwardHullFrame3d.GetFaceNormal(in FixedTriangle triangle) =>
 195648        WideTriangleRelations.GetScaledTriangleLocalNormal(triangle, this).Transform(GeometryBasis);
 49    WideDirection3d IForwardHullFrame3d.GetEdgeDirection(Vector3d first, Vector3d second) =>
 430150        WideDirection3d.GetLocalEdge(this, first, second).Transform(GeometryBasis);
 51    WideDirection3d IForwardHullFrame3d.GetInwardAxis(in FixedTriangle triangle, Vector3d first, Vector3d second) =>
 3052        WideDirection3d.Cross(WideTriangleRelations.GetScaledTriangleLocalNormal(triangle, this),
 3053            WideDirection3d.GetLocalEdge(this, first, second)).Transform(GeometryBasis);
 54    bool IForwardHullFrame3d.TryGetTriangleHalfPlanes(in FixedTriangle triangle, in RationalPoint3d point,
 279455        Span<Signed832> values) => WideTriangleRelations.GetScaledTriangleHalfPlanes(triangle, this, point, values);
 56
 57    internal static ScaledRigidFrame3d Rigid(Vector3d origin, FixedQuaternion rotation) =>
 17758        new(origin, rotation, Vector3d.Zero, Vector3d.One, rotation, Vector3d.Zero, Vector3d.One);
 59
 60    internal ScaledRigidFrame3d(
 61        Vector3d translation,
 62        FixedQuaternion placementRotation,
 63        Vector3d offset,
 64        Vector3d ownerScale,
 65        FixedQuaternion geometryRotation,
 66        Vector3d reference,
 67        Vector3d partScale)
 68    {
 72469        this = default;
 72470        if (!placementRotation.IsNormalized())
 171            throw new ArgumentException("The placement rotation must be normalized.", nameof(placementRotation));
 72372        if (!geometryRotation.IsNormalized())
 173            throw new ArgumentException("The geometry rotation must be normalized.", nameof(geometryRotation));
 74
 72275        _reference = reference;
 72276        _translation = translation;
 72277        _sameRotation = placementRotation == geometryRotation;
 72278        _identityUnit = placementRotation == FixedQuaternion.Identity
 72279            && geometryRotation == FixedQuaternion.Identity
 72280            && ownerScale == Vector3d.One && partScale == Vector3d.One;
 72281        GeometryBasis = new WideRationalBasis3d(geometryRotation);
 72282        GeometryRotation = geometryRotation;
 72283        _scaleX = Fixed64.GetExactRawProduct(ownerScale.X, partScale.X);
 72284        _scaleY = Fixed64.GetExactRawProduct(ownerScale.Y, partScale.Y);
 72285        _scaleZ = Fixed64.GetExactRawProduct(ownerScale.Z, partScale.Z);
 86        // Placement consumes owner scale only. Its Q denominator is lifted
 87        // to the same Q^2 denominator as the centered three-factor product.
 72288        _offsetX = WideArithmetic.ShiftLeftSigned192By32(Fixed64.GetExactRawProduct(offset.X, ownerScale.X));
 72289        _offsetY = WideArithmetic.ShiftLeftSigned192By32(Fixed64.GetExactRawProduct(offset.Y, ownerScale.Y));
 72290        _offsetZ = WideArithmetic.ShiftLeftSigned192By32(Fixed64.GetExactRawProduct(offset.Z, ownerScale.Z));
 91
 92        // Frame inputs are immutable. Classify their exact rigid mapping once,
 93        // rather than repeating scale/reference products for every support query.
 72294        _isRigid = _sameRotation && _scaleX.Equals(ScaleDenominator)
 72295            && _scaleY.Equals(ScaleDenominator) && _scaleZ.Equals(ScaleDenominator)
 72296            && _offsetX.Equals(ScaleReference(_reference.X))
 72297            && _offsetY.Equals(ScaleReference(_reference.Y))
 72298            && _offsetZ.Equals(ScaleReference(_reference.Z));
 99
 722100        WideRationalBasis3d placementBasis = _sameRotation ? GeometryBasis : new(placementRotation);
 722101        _placementDenominator = _sameRotation ? Signed192.Signed(1L) : placementBasis.Denominator;
 722102        RotationDenominator = Signed192.NarrowProven(
 722103            WideArithmetic.MultiplySigned192(GeometryBasis.Denominator, _placementDenominator));
 722104        Denominator = WideArithmetic.MultiplySigned192(RotationDenominator, ScaleDenominator);
 722105        _translationX = GetTranslation(translation.X, placementBasis.Xx, placementBasis.Yx, placementBasis.Zx);
 722106        _translationY = GetTranslation(translation.Y, placementBasis.Xy, placementBasis.Yy, placementBasis.Zy);
 722107        _translationZ = GetTranslation(translation.Z, placementBasis.Xz, placementBasis.Yz, placementBasis.Zz);
 722108    }
 109
 110    /// <summary>
 111    /// Returns centered scaled raw-coordinate numerators over the shared Q^2
 112    /// denominator. A full-domain difference times two scalar factors fits 192 bits.
 113    /// </summary>
 114    internal void GetScaledLocalPointNumerators(Vector3d source, out Signed192 x, out Signed192 y, out Signed192 z)
 115    {
 287710116        x = GetScaledDifference(source.X, _reference.X, _scaleX);
 287710117        y = GetScaledDifference(source.Y, _reference.Y, _scaleY);
 287710118        z = GetScaledDifference(source.Z, _reference.Z, _scaleZ);
 287710119    }
 120
 121    internal RationalPoint3d GetPoint(Vector3d source)
 122    {
 275502123        if (_identityUnit)
 124        {
 125            // Preserve the shared Q^2 denominator with shifts, without rotation products.
 67830126            return new RationalPoint3d(GetOrdinaryCoordinate(source.X, _reference.X, _offsetX, _translationX),
 67830127                GetOrdinaryCoordinate(source.Y, _reference.Y, _offsetY, _translationY),
 67830128                GetOrdinaryCoordinate(source.Z, _reference.Z, _offsetZ, _translationZ), Denominator);
 129        }
 130
 207672131        GetScaledLocalPointNumerators(source, out Signed192 x, out Signed192 y, out Signed192 z);
 207672132        if (_sameRotation)
 133        {
 175931134            x = WideArithmetic.AddSigned192(x, _offsetX);
 175931135            y = WideArithmetic.AddSigned192(y, _offsetY);
 175931136            z = WideArithmetic.AddSigned192(z, _offsetZ);
 137        }
 207672138        return new RationalPoint3d(
 207672139            GetWorldCoordinate(x, y, z, GeometryBasis.Xx, GeometryBasis.Yx, GeometryBasis.Zx, _translationX),
 207672140            GetWorldCoordinate(x, y, z, GeometryBasis.Xy, GeometryBasis.Yy, GeometryBasis.Zy, _translationY),
 207672141            GetWorldCoordinate(x, y, z, GeometryBasis.Xz, GeometryBasis.Yz, GeometryBasis.Zz, _translationZ),
 207672142            Denominator);
 143    }
 144
 2963145    internal bool TryGetPoint(Vector3d source, out Vector3d point) => GetPoint(source).TryGetPoint(out point);
 146
 147    internal RationalPoint3d GetScaledLocalPoint(Vector3d scaledLocalPoint)
 148    {
 8149        Signed192 x = ScaleReference(scaledLocalPoint.X);
 8150        Signed192 y = ScaleReference(scaledLocalPoint.Y);
 8151        Signed192 z = ScaleReference(scaledLocalPoint.Z);
 8152        if (_sameRotation)
 153        {
 2154            x = WideArithmetic.AddSigned192(x, _offsetX);
 2155            y = WideArithmetic.AddSigned192(y, _offsetY);
 2156            z = WideArithmetic.AddSigned192(z, _offsetZ);
 157        }
 8158        return new RationalPoint3d(
 8159            GetWorldCoordinate(x, y, z, GeometryBasis.Xx, GeometryBasis.Yx, GeometryBasis.Zx, _translationX),
 8160            GetWorldCoordinate(x, y, z, GeometryBasis.Xy, GeometryBasis.Yy, GeometryBasis.Zy, _translationY),
 8161            GetWorldCoordinate(x, y, z, GeometryBasis.Xz, GeometryBasis.Yz, GeometryBasis.Zz, _translationZ), Denominato
 162    }
 163
 164    internal bool TryGetScaledLocalPointIn(Vector3d worldPoint, out Vector3d scaledLocalPoint)
 165    {
 14166        GetScaledLocalPointNumeratorsIn(worldPoint, out Signed576 x, out Signed576 y, out Signed576 z,
 14167            out Signed320 denominator);
 14168        Signed576 d = Signed576.ExtendValue(denominator);
 14169        bool representable = Fixed64.TryGetSignedRawRatio(x, d, out Fixed64 px)
 14170            & Fixed64.TryGetSignedRawRatio(y, d, out Fixed64 py)
 14171            & Fixed64.TryGetSignedRawRatio(z, d, out Fixed64 pz);
 14172        scaledLocalPoint = representable ? new Vector3d(px, py, pz) : default;
 14173        return representable;
 174    }
 175
 176    internal bool IsScaledLocalPointExact(Vector3d source, Vector3d roundedCentered)
 177    {
 4178        GetScaledLocalPointNumerators(source, out Signed192 x, out Signed192 y, out Signed192 z);
 4179        return x.Equals(ScaleReference(roundedCentered.X))
 4180            & y.Equals(ScaleReference(roundedCentered.Y))
 4181            & z.Equals(ScaleReference(roundedCentered.Z));
 182    }
 183
 184    internal WideAxis3 GetSourceDirectionNumerators(Vector3d worldDirection)
 185    {
 24186        Signed192 x = Signed192.Raw(worldDirection.X), y = Signed192.Raw(worldDirection.Y), z = Signed192.Raw(worldDirec
 187        // Rotation coefficients <65 bits, direction components <=64 and scale
 188        // products <=127 keep each complete source covector below 258 bits.
 8189        return new WideAxis3(
 8190            Signed320.NarrowValue(WideArithmetic.MultiplySigned320(
 8191                Rotate(x, y, z, GeometryBasis.Xx, GeometryBasis.Xy, GeometryBasis.Xz), _scaleX)),
 8192            Signed320.NarrowValue(WideArithmetic.MultiplySigned320(
 8193                Rotate(x, y, z, GeometryBasis.Yx, GeometryBasis.Yy, GeometryBasis.Yz), _scaleY)),
 8194            Signed320.NarrowValue(WideArithmetic.MultiplySigned320(
 8195                Rotate(x, y, z, GeometryBasis.Zx, GeometryBasis.Zy, GeometryBasis.Zz), _scaleZ)));
 196    }
 197
 198    /// <summary>Transforms an authored endpoint difference, whose components have magnitude below 2^64.</summary>
 199    internal WideAxis3 GetWorldDirectionNumerators(in WideAxis3 authoredRay)
 200    {
 201        // A halfspace direction has no metric scale. Rigid endpoint
 202        // differences need only the rotation numerator; retaining unit Q^2
 203        // scale factors needlessly enlarges every downstream fan product.
 3204        if (IsRigid)
 1205            return WideRigidProjection.TransformLocalAxis(GeometryBasis,
 1206                Signed192.NarrowProven(authoredRay.X), Signed192.NarrowProven(authoredRay.Y), Signed192.NarrowProven(aut
 2207        Signed192 x = Signed192.NarrowValue(WideArithmetic.MultiplySigned320(authoredRay.X, _scaleX));
 2208        Signed192 y = Signed192.NarrowValue(WideArithmetic.MultiplySigned320(authoredRay.Y, _scaleY));
 2209        Signed192 z = Signed192.NarrowValue(WideArithmetic.MultiplySigned320(authoredRay.Z, _scaleZ));
 2210        return new WideAxis3(Rotate(x, y, z, GeometryBasis.Xx, GeometryBasis.Yx, GeometryBasis.Zx),
 2211            Rotate(x, y, z, GeometryBasis.Xy, GeometryBasis.Yy, GeometryBasis.Zy),
 2212            Rotate(x, y, z, GeometryBasis.Xz, GeometryBasis.Yz, GeometryBasis.Zz));
 213    }
 214
 215    internal FixedBoundBox GetWorldBounds(Vector3d sourceMin, Vector3d sourceMax)
 216    {
 17217        if (IsRigid)
 8218            return FixedBoundBox.FromRelativeRotatedBoundsClippedToDomain(RigidOrigin, Rotation, sourceMin, sourceMax,
 8219                Vector3d.Zero, FixedQuaternion.Identity);
 9220        Vector3d min = new(Fixed64.MaxValue, Fixed64.MaxValue, Fixed64.MaxValue);
 9221        Vector3d max = new(Fixed64.MinValue, Fixed64.MinValue, Fixed64.MinValue);
 162222        for (int corner = 0; corner < 8; corner++)
 223        {
 72224            RationalPoint3d point = GetPoint(GetCorner(sourceMin, sourceMax, corner));
 72225            Signed576 denominator = Signed576.ExtendValue(point.Denominator);
 72226            IncludeBound(Signed576.ExtendValue(point.X), denominator, ref min.X, ref max.X);
 72227            IncludeBound(Signed576.ExtendValue(point.Y), denominator, ref min.Y, ref max.Y);
 72228            IncludeBound(Signed576.ExtendValue(point.Z), denominator, ref min.Z, ref max.Z);
 229        }
 9230        return FixedBoundBox.FromMinMax(min, max);
 231    }
 232
 233    internal bool TryGetSourceBounds(Vector3d worldMin, Vector3d worldMax, out FixedBoundBox bounds)
 234    {
 13235        if (_scaleX.IsZero || _scaleY.IsZero || _scaleZ.IsZero)
 236        {
 3237            bounds = default;
 3238            return false;
 239        }
 10240        Vector3d min = new(Fixed64.MaxValue, Fixed64.MaxValue, Fixed64.MaxValue);
 10241        Vector3d max = new(Fixed64.MinValue, Fixed64.MinValue, Fixed64.MinValue);
 180242        for (int corner = 0; corner < 8; corner++)
 243        {
 80244            GetSourcePointNumerators(GetCorner(worldMin, worldMax, corner),
 80245                out Signed576 x, out Signed576 y, out Signed576 z,
 80246                out Signed576 dx, out Signed576 dy, out Signed576 dz);
 80247            IncludeBound(x, dx, ref min.X, ref max.X);
 80248            IncludeBound(y, dy, ref min.Y, ref max.Y);
 80249            IncludeBound(z, dz, ref min.Z, ref max.Z);
 250        }
 10251        bounds = FixedBoundBox.FromMinMax(min, max);
 10252        return true;
 253    }
 254
 255    internal bool TryGetBoundsIn(Vector3d sourceMin, Vector3d sourceMax,
 256        in ScaledRigidFrame3d target, out FixedBoundBox bounds)
 257    {
 6258        if (target._scaleX.IsZero || target._scaleY.IsZero || target._scaleZ.IsZero)
 259        {
 4260            bounds = default;
 4261            return false;
 262        }
 2263        Vector3d min = new(Fixed64.MaxValue, Fixed64.MaxValue, Fixed64.MaxValue);
 2264        Vector3d max = new(Fixed64.MinValue, Fixed64.MinValue, Fixed64.MinValue);
 36265        for (int corner = 0; corner < 8; corner++)
 266        {
 16267            RationalPoint3d world = GetPoint(GetCorner(sourceMin, sourceMax, corner));
 128268            for (int axis = 0; axis < 3; axis++)
 269            {
 48270                target.GetSourceCoordinateTransform(axis, out Signed576 x, out Signed576 y, out Signed576 z,
 48271                    out Signed576 offset, out Signed576 divisor);
 48272                Signed832 numerator = WideArithmetic.AddSigned832(WideArithmetic.AddSigned832(
 48273                    WideArithmetic.MultiplySigned576ToSigned832(x, world.X),
 48274                    WideArithmetic.MultiplySigned576ToSigned832(y, world.Y)),
 48275                    WideArithmetic.AddSigned832(WideArithmetic.MultiplySigned576ToSigned832(z, world.Z),
 48276                        WideArithmetic.MultiplySigned576ToSigned832(offset, world.Denominator)));
 48277                Signed832 denominator = WideArithmetic.MultiplySigned576ToSigned832(divisor, world.Denominator);
 278                // Both complete affine ratios retain the source's Q^2 factor.
 279                // Cancel it exactly before the bounded 576-bit bound owner.
 96280                Signed576 n = RemoveScaleDenominator(numerator), d = RemoveScaleDenominator(denominator);
 48281                min[axis] = FixedMath.Min(min[axis], WideGeometry.GetRationalBoundClippedToDomain(n, d, true));
 48282                max[axis] = FixedMath.Max(max[axis], WideGeometry.GetRationalBoundClippedToDomain(n, d, false));
 283            }
 284        }
 2285        bounds = FixedBoundBox.FromMinMax(min, max);
 2286        return true;
 287    }
 288
 289    /// <summary>
 290    /// Inverts this frame without materializing its transformed reference.
 291    /// Each source coordinate has its own scale denominator; zero scale makes
 292    /// that coordinate undefined and therefore makes materialization fail.
 293    /// </summary>
 294    internal void GetSourcePointNumerators(Vector3d worldPoint,
 295        out Signed576 x, out Signed576 y, out Signed576 z,
 296        out Signed576 denominatorX, out Signed576 denominatorY, out Signed576 denominatorZ)
 297    {
 88298        GetScaledLocalPointNumeratorsIn(worldPoint, out Signed576 inverseX, out Signed576 inverseY,
 88299            out Signed576 inverseZ, out Signed320 rotationDenominator);
 88300        GetSourceCoordinate(inverseX, rotationDenominator,
 88301            _reference.X, _scaleX, out x, out denominatorX);
 88302        GetSourceCoordinate(inverseY, rotationDenominator,
 88303            _reference.Y, _scaleY, out y, out denominatorY);
 88304        GetSourceCoordinate(inverseZ, rotationDenominator,
 88305            _reference.Z, _scaleZ, out z, out denominatorZ);
 88306    }
 307
 308    internal bool TryGetSourceBoundsFromScaledLocal(Vector3d scaledMin, Vector3d scaledMax, out FixedBoundBox bounds)
 309    {
 17310        if (_scaleX.IsZero || _scaleY.IsZero || _scaleZ.IsZero) { bounds = default; return false; }
 16311        Vector3d min = default, max = default;
 8312        Signed320 one = Signed320.ExtendValue(Signed192.Signed(1));
 64313        for (int axis = 0; axis < 3; axis++)
 314        {
 48315            min[axis] = Fixed64.MaxValue; max[axis] = Fixed64.MinValue;
 144316            for (int end = 0; end < 2; end++)
 317            {
 48318                Fixed64 value = end == 0 ? scaledMin[axis] : scaledMax[axis];
 48319                GetSourceCoordinate(Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Raw(value))), one,
 48320                    _reference[axis], GetScale(axis), out Signed576 numerator, out Signed576 denominator);
 48321                min[axis] = FixedMath.Min(min[axis], WideGeometry.GetRationalBoundClippedToDomain(numerator, denominator
 48322                max[axis] = FixedMath.Max(max[axis], WideGeometry.GetRationalBoundClippedToDomain(numerator, denominator
 323            }
 324        }
 8325        bounds = FixedBoundBox.FromMinMax(min, max);
 8326        return true;
 327    }
 328    internal bool HasSameMapping(in ScaledRigidFrame3d other)
 329    {
 110330        for (int axis = 0; axis < 3; axis++)
 331        {
 90332            WideAxis3 first = GeometryBasis.GetAxis(axis), second = other.GeometryBasis.GetAxis(axis);
 90333            Signed192 firstScale = GetScale(axis), secondScale = other.GetScale(axis);
 45334            if (!SameLinearCoordinate(first.X, firstScale, other.GeometryBasis.Denominator,
 45335                    second.X, secondScale, GeometryBasis.Denominator)
 45336                || !SameLinearCoordinate(first.Y, firstScale, other.GeometryBasis.Denominator,
 45337                    second.Y, secondScale, GeometryBasis.Denominator)
 45338                || !SameLinearCoordinate(first.Z, firstScale, other.GeometryBasis.Denominator,
 57339                    second.Z, secondScale, GeometryBasis.Denominator)) return false;
 340        }
 20341        RationalPoint3d origin = GetPoint(Vector3d.Zero), otherOrigin = other.GetPoint(Vector3d.Zero);
 342        // Both point denominators contain the same Q^2 factor; cancel it
 343        // before comparing independently retained placement origins.
 10344        return SameMappedCoordinate(origin.X, other.RotationDenominator, otherOrigin.X, RotationDenominator)
 10345            & SameMappedCoordinate(origin.Y, other.RotationDenominator, otherOrigin.Y, RotationDenominator)
 10346            & SameMappedCoordinate(origin.Z, other.RotationDenominator, otherOrigin.Z, RotationDenominator);
 347    }
 348
 349    /// <summary>
 350    /// Returns one inverse coordinate as (x*worldX + y*worldY + z*worldZ +
 351    /// offset)/divisor, where world components and the result are raw coordinates.
 352    /// The axis is in [0,2]; a zero scale produces a zero divisor.
 353    /// </summary>
 354    internal void GetSourceCoordinateTransform(int axis, out Signed576 x, out Signed576 y, out Signed576 z,
 355        out Signed576 offset, out Signed576 divisor)
 356    {
 128357        WideAxis3 column = GeometryBasis.GetAxis(axis);
 358        // Every inverse coefficient has a common Q^2 factor; cancel it here
 359        // so chained geometry does not multiply redundant scale denominators.
 128360        x = WideArithmetic.MultiplySigned320(column.X, Denominator);
 128361        y = WideArithmetic.MultiplySigned320(column.Y, Denominator);
 128362        z = WideArithmetic.MultiplySigned320(column.Z, Denominator);
 128363        divisor = WideArithmetic.MultiplySigned576(
 128364            Signed576.ExtendValue(WideArithmetic.MultiplySigned192(RotationDenominator, GeometryBasis.Denominator)), Get
 128365        RationalPoint3d origin = GetPoint(_reference);
 128366        Signed576 projectedOrigin = WideArithmetic.AddSigned576(WideArithmetic.AddSigned576(
 128367            WideArithmetic.MultiplySigned320(origin.X, column.X), WideArithmetic.MultiplySigned320(origin.Y, column.Y)),
 128368            WideArithmetic.MultiplySigned320(origin.Z, column.Z));
 128369        offset = WideArithmetic.SubtractSigned576(WideArithmetic.MultiplySigned576(divisor, _reference[axis].m_rawValue)
 128370            projectedOrigin);
 128371    }
 372
 532373    private Signed192 GetScale(int axis) => axis switch { 0 => _scaleX, 1 => _scaleY, _ => _scaleZ };
 374
 375    private static bool SameLinearCoordinate(Signed320 first, Signed192 firstScale, Signed192 otherDenominator,
 376        Signed320 second, Signed192 secondScale, Signed192 denominator) =>
 114377        WideArithmetic.SubtractSigned576(
 114378            WideArithmetic.MultiplySigned576(WideArithmetic.MultiplySigned320(first, firstScale), otherDenominator),
 114379            WideArithmetic.MultiplySigned576(WideArithmetic.MultiplySigned320(second, secondScale), denominator)).IsZero
 380
 381    private static bool SameMappedCoordinate(Signed320 first, Signed192 otherDenominator,
 382        Signed320 second, Signed192 denominator) =>
 30383        WideArithmetic.SubtractSigned576(WideArithmetic.MultiplySigned320(first, otherDenominator),
 30384            WideArithmetic.MultiplySigned320(second, denominator)).IsZero;
 385
 386    private static Vector3d GetCorner(Vector3d min, Vector3d max, int corner) =>
 168387        new((corner & 1) == 0 ? min.X : max.X, (corner & 2) == 0 ? min.Y : max.Y,
 168388            (corner & 4) == 0 ? min.Z : max.Z);
 389
 390    private static Signed576 RemoveScaleDenominator(Signed832 value) =>
 96391        new(value.Word9, value.Word8, value.Word7, value.Word6, value.Word5,
 96392            value.Word4, value.Word3, value.Word2, value.Word1);
 393
 394    private static void IncludeBound(Signed576 numerator, Signed576 denominator, ref Fixed64 min, ref Fixed64 max)
 395    {
 456396        min = FixedMath.Min(min, WideGeometry.GetRationalBoundClippedToDomain(numerator, denominator, minimum: true));
 456397        max = FixedMath.Max(max, WideGeometry.GetRationalBoundClippedToDomain(numerator, denominator, minimum: false));
 456398    }
 399
 400    private static Signed192 ScaleReference(Fixed64 value) =>
 908401        WideArithmetic.ShiftLeftSigned192By32(WideArithmetic.ShiftLeftSigned192By32(Signed192.Raw(value)));
 402
 403    private void GetScaledLocalPointNumeratorsIn(Vector3d worldPoint,
 404        out Signed576 x, out Signed576 y, out Signed576 z, out Signed320 denominator)
 405    {
 102406        GetPoint(_reference).GetLocalPointNumerators(worldPoint, GeometryRotation,
 102407            out Signed576 inverseX, out Signed576 inverseY, out Signed576 inverseZ, out denominator);
 408        // The rigid projection gives reference-worldPoint; negate to obtain the
 409        // displacement from the exact geometry origin to the requested point.
 102410        x = WideArithmetic.SubtractSigned576(default, inverseX);
 102411        y = WideArithmetic.SubtractSigned576(default, inverseY);
 102412        z = WideArithmetic.SubtractSigned576(default, inverseZ);
 102413    }
 414
 415    private static void GetSourceCoordinate(Signed576 localNumerator, Signed320 localDenominator,
 416        Fixed64 reference, Signed192 scale, out Signed576 numerator, out Signed576 denominator)
 417    {
 312418        denominator = WideArithmetic.MultiplySigned320(localDenominator, scale);
 419        // Three source/target rotations, two scalar factors and reference
 420        // multiplication keep these inverse numerators below 452 bits.
 312421        numerator = WideArithmetic.AddSigned576(
 312422            WideArithmetic.MultiplySigned576(localNumerator, ScaleDenominator),
 312423            WideArithmetic.MultiplySigned576(denominator, reference.m_rawValue));
 312424    }
 425
 426    private Signed320 GetTranslation(Fixed64 translation, Signed192 axisX, Signed192 axisY, Signed192 axisZ)
 427    {
 2166428        Signed576 result = WideArithmetic.MultiplySigned320(Denominator, Signed192.Raw(translation));
 2166429        if (!_sameRotation)
 430        {
 294431            Signed320 rotated = Rotate(_offsetX, _offsetY, _offsetZ, axisX, axisY, axisZ);
 294432            result = WideArithmetic.AddSigned576(result,
 294433                WideArithmetic.MultiplySigned320(rotated, GeometryBasis.Denominator));
 434        }
 2166435        return Signed320.NarrowValue(result);
 436    }
 437
 438    private Signed320 GetWorldCoordinate(Signed192 x, Signed192 y, Signed192 z,
 439        Signed192 axisX, Signed192 axisY, Signed192 axisZ, Signed320 translation)
 440    {
 623040441        Signed576 result = WideArithmetic.AddSigned576(Signed576.ExtendValue(translation),
 623040442            WideArithmetic.MultiplySigned320(Rotate(x, y, z, axisX, axisY, axisZ), _placementDenominator));
 443        // Normalized quaternion D < Q^2 + 258Q < (17/16)Q^2.
 444        // The geometry numerator vector has norm < sqrt(3)*2^190.
 445        // Two basis denominators give magnitude < (7/4)*(17/16)^2*2^318,
 446        // leaving more than 2^312 of headroom below the signed 320-bit limit.
 447        // Full-domain placement and translation together are below 2^290.
 623040448        return Signed320.NarrowValue(result);
 449    }
 450
 451    private static Signed192 GetScaledDifference(Fixed64 source, Fixed64 reference, Signed192 scale) =>
 863130452        Signed192.NarrowProven(WideArithmetic.MultiplySigned192(
 863130453            WideArithmetic.Difference(source, reference), scale));
 454
 455    private static Signed320 GetOrdinaryCoordinate(Fixed64 source, Fixed64 reference, Signed192 offset, Signed320 transl
 203490456        WideArithmetic.AddSigned320(translation, Signed320.ExtendValue(
 203490457            WideArithmetic.ShiftLeftSigned192By32(WideArithmetic.ShiftLeftSigned192By32(
 203490458                WideArithmetic.AddSigned192(WideArithmetic.Difference(source, reference),
 203490459                    Signed192.Signed(unchecked((long)offset.Middle)))))));
 460
 461    private static Signed320 Rotate(Signed192 x, Signed192 y, Signed192 z,
 462        Signed192 axisX, Signed192 axisY, Signed192 axisZ) =>
 623364463        WideArithmetic.AddSigned320(WideArithmetic.AddSigned320(
 623364464            WideArithmetic.MultiplySigned192(x, axisX), WideArithmetic.MultiplySigned192(y, axisY)),
 623364465            WideArithmetic.MultiplySigned192(z, axisZ));
 466}

Methods/Properties

.cctor()
get_IsRigid()
get_RigidOrigin()
get_Rotation()
get_HasLocalPlacement()
FixedMathSharp.Geometry.IForwardHullFrame3d.get_RotationDenominator()
FixedMathSharp.Geometry.IForwardHullFrame3d.get_Denominator()
FixedMathSharp.Geometry.IForwardHullFrame3d.GetPoint(FixedMathSharp.Vector3d)
FixedMathSharp.Geometry.IForwardHullFrame3d.GetFaceNormal(System.Runtime.InteropServices.InAttribute))
FixedMathSharp.Geometry.IForwardHullFrame3d.GetEdgeDirection(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
FixedMathSharp.Geometry.IForwardHullFrame3d.GetInwardAxis(System.Runtime.InteropServices.InAttribute),FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
FixedMathSharp.Geometry.IForwardHullFrame3d.TryGetTriangleHalfPlanes(System.Runtime.InteropServices.InAttribute),System.Span`1<FixedMathSharp.Signed832>)
Rigid(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
.ctor(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
GetScaledLocalPointNumerators(FixedMathSharp.Vector3d,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)
GetPoint(FixedMathSharp.Vector3d)
TryGetPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
GetScaledLocalPoint(FixedMathSharp.Vector3d)
TryGetScaledLocalPointIn(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
IsScaledLocalPointExact(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
GetSourceDirectionNumerators(FixedMathSharp.Vector3d)
GetWorldDirectionNumerators(FixedMathSharp.Geometry.WideAxis3&)
GetWorldBounds(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
TryGetSourceBounds(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedBoundBox&)
TryGetBoundsIn(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.FixedBoundBox&)
GetSourcePointNumerators(FixedMathSharp.Vector3d,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
TryGetSourceBoundsFromScaledLocal(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedBoundBox&)
HasSameMapping(FixedMathSharp.Geometry.ScaledRigidFrame3d&)
GetSourceCoordinateTransform(System.Int32,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
GetScale(System.Int32)
SameLinearCoordinate(FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
SameMappedCoordinate(FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed192)
GetCorner(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Int32)
RemoveScaleDenominator(FixedMathSharp.Signed832)
IncludeBound(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
ScaleReference(FixedMathSharp.Fixed64)
GetScaledLocalPointNumeratorsIn(FixedMathSharp.Vector3d,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed320&)
GetSourceCoordinate(FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
GetTranslation(FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetWorldCoordinate(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320)
GetScaledDifference(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed192)
GetOrdinaryCoordinate(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed320)
Rotate(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)