| | | 1 | | //======================================================================= |
| | | 2 | | // WideTriangleConeIntersection.ScaledFrame.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 | | |
| | | 8 | | using System; |
| | | 9 | | |
| | | 10 | | namespace FixedMathSharp.Geometry; |
| | | 11 | | |
| | | 12 | | /// <content>Exact source-frame ingress for finite triangle/cone minimum-axial queries.</content> |
| | | 13 | | internal static partial class WideTriangleConeIntersection |
| | | 14 | | { |
| | | 15 | | private const int ScaledQueryWords = 32; |
| | | 16 | | |
| | | 17 | | internal static bool TryGetMinimumAxialPoint(in FixedTriangle triangle, in ScaledRigidFrame3d frame, |
| | | 18 | | Vector3d apex, Vector3d axis, Fixed64 height, Fixed64 radius, |
| | | 19 | | out FixedPointAnchor point) |
| | | 20 | | { |
| | 30 | 21 | | if (frame.IsRigid) |
| | | 22 | | { |
| | 2 | 23 | | bool found = TryGetMinimumAxialPoint(triangle,frame.RigidOrigin,frame.Rotation,apex,axis,height,radius,out V |
| | 2 | 24 | | point = found ? new FixedPointAnchor(frame.RigidOrigin,frame.Rotation,local) : default; |
| | 2 | 25 | | return found; |
| | | 26 | | } |
| | 84 | 27 | | bool hasPoint=false;point=default;Fixed64 best=Fixed64.MaxValue; |
| | 224 | 28 | | for(int edge=0;edge<3;edge++) |
| | | 29 | | { |
| | 84 | 30 | | if(!TryGetScaledConeEdgePoint(triangle.GetEdge(edge),frame,apex,axis,height,radius,out FixedPointAnchor cand |
| | 27 | 31 | | Fixed64 axial=GetScaledConeAxial(candidate,apex,axis,height); |
| | 27 | 32 | | if(hasPoint&&axial>=best)continue; |
| | 45 | 33 | | hasPoint=true;point=candidate;best=axial; |
| | | 34 | | } |
| | 28 | 35 | | if(TryGetScaledConeFacePoint(triangle,frame,apex,axis,height,radius,hasPoint,out FixedPointAnchor face,out Fixed |
| | 40 | 36 | | &&(!hasPoint||faceAxial<best)){point=face;hasPoint=true;} |
| | 28 | 37 | | return hasPoint; |
| | | 38 | | } |
| | | 39 | | |
| | | 40 | | private static Fixed64 GetScaledConeAxial(in FixedPointAnchor point,Vector3d apex,Vector3d axis,Fixed64 height) => |
| | 27 | 41 | | FixedMath.Min(point.ProjectNonNegativeOffsetFrom(new FixedPointAnchor(apex,FixedQuaternion.Identity,Vector3d.Zer |
| | | 42 | | |
| | 273 | 43 | | private static WideDirection3d GetScaledConeRelativePoint(in RationalPoint3d point,Vector3d apex) => new( |
| | 273 | 44 | | WideArithmetic.SubtractSigned576(Signed576.ExtendValue(point.X),WideArithmetic.MultiplySigned320(point.Denominat |
| | 273 | 45 | | WideArithmetic.SubtractSigned576(Signed576.ExtendValue(point.Y),WideArithmetic.MultiplySigned320(point.Denominat |
| | 273 | 46 | | WideArithmetic.SubtractSigned576(Signed576.ExtendValue(point.Z),WideArithmetic.MultiplySigned320(point.Denominat |
| | | 47 | | |
| | | 48 | | private static bool TryGetScaledConeEdgePoint(in FixedSegment edge,in ScaledRigidFrame3d frame, |
| | | 49 | | Vector3d apex,Vector3d axis,Fixed64 height,Fixed64 radius,out FixedPointAnchor point) |
| | | 50 | | { |
| | 84 | 51 | | point=default; |
| | 84 | 52 | | WideDirection3d first=GetScaledConeRelativePoint(frame.GetPoint(edge.Start),apex); |
| | 84 | 53 | | WideDirection3d last=GetScaledConeRelativePoint(frame.GetPoint(edge.End),apex); |
| | 84 | 54 | | WideDirection3d delta=new(WideArithmetic.SubtractSigned576(last.X,first.X), |
| | 84 | 55 | | WideArithmetic.SubtractSigned576(last.Y,first.Y),WideArithmetic.SubtractSigned576(last.Z,first.Z)); |
| | 84 | 56 | | var direction=new WideDirection3d(new WideAxis3(Signed320.ExtendValue(Signed192.Raw(axis.X)), |
| | 84 | 57 | | Signed320.ExtendValue(Signed192.Raw(axis.Y)),Signed320.ExtendValue(Signed192.Raw(axis.Z)))); |
| | 252 | 58 | | Signed832 q=direction.SquaredLength, startAxial=WideDirection3d.Dot(first,direction), velocity=WideDirection3d.D |
| | 168 | 59 | | Signed832 start=WideArithmetic.MultiplySigned832(startAxial,Scale), end=WideArithmetic.MultiplySigned832(WideAri |
| | 84 | 60 | | Signed832 maximum=default; |
| | | 61 | | // The denominator may exceed192 after independent placement rotations. |
| | | 62 | | // Keep the complete product in the borrowed coefficient bank below. |
| | | 63 | | const int words=ScaledQueryWords; |
| | 168 | 64 | | Span<ulong> values=stackalloc ulong[14*words];Span<int> signs=stackalloc int[14]; |
| | 168 | 65 | | var a=ContactQuadratic.At(values,signs,0,words);var b=ContactQuadratic.At(values,signs,1,words); |
| | 168 | 66 | | var c=ContactQuadratic.At(values,signs,2,words);var work=ContactQuadratic.At(values,signs,3,words); |
| | 168 | 67 | | var term=ContactQuadratic.At(values,signs,4,words);var axial=ContactQuadratic.At(values,signs,5,words); |
| | 84 | 68 | | var radial=ContactQuadratic.At(values,signs,6,words); |
| | 168 | 69 | | work.Set(q);ContactQuadratic.Scale(work,Signed576.ExtendValue(frame.Denominator),term); |
| | 84 | 70 | | ContactQuadratic.Scale(term,Signed576.ExtendValue(Signed192.Raw(height)),work); |
| | 84 | 71 | | maximum=PackScaledCone832(work); |
| | 336 | 72 | | Signed832 lowerN=default,lowerD=Signed832.ExtendValue(Signed192.One),upperN=lowerD,upperD=lowerD; |
| | 84 | 73 | | if(!WideTriangleRelations.ClipScaledHalfPlane(start,end,ref lowerN,ref lowerD,ref upperN,ref upperD) |
| | 84 | 74 | | ||!WideTriangleRelations.ClipScaledHalfPlane(WideArithmetic.SubtractSigned832(maximum,start), |
| | 101 | 75 | | WideArithmetic.SubtractSigned832(maximum,end),ref lowerN,ref lowerD,ref upperN,ref upperD))return false; |
| | 67 | 76 | | BuildScaledConeEdgeCoefficient(delta,delta,velocity,velocity,q,height,radius,a,work,term,axial,radial); |
| | 67 | 77 | | BuildScaledConeEdgeCoefficient(first,delta,startAxial,velocity,q,height,radius,b,work,term,axial,radial); |
| | 67 | 78 | | BuildScaledConeEdgeCoefficient(first,first,startAxial,startAxial,q,height,radius,c,work,term,axial,radial); |
| | 67 | 79 | | if(!WideFiniteConeIntersection.TrySolveBoundedUnitPolynomial(a,b,c,lowerN,lowerD,upperN,upperD, |
| | 105 | 80 | | Fixed64.MaxValue,out Fixed64 entry,out Fixed64 exit))return false; |
| | 29 | 81 | | Fixed64 parameter=velocity.Sign<0?exit:entry; |
| | 58 | 82 | | work.Set(Signed576.ExtendValue(Signed192.Raw(parameter)));term.Set(Signed576.ExtendValue(MaximumParameter)); |
| | 29 | 83 | | return WideTriangleRelations.TryGetSegmentPointAnchor(frame,edge,work,term,apex,out point); |
| | | 84 | | } |
| | | 85 | | |
| | | 86 | | private static void BuildScaledConeEdgeCoefficient(in WideDirection3d first,in WideDirection3d second, |
| | | 87 | | Signed832 firstAxial,Signed832 secondAxial,Signed832 q,Fixed64 height,Fixed64 radius, |
| | | 88 | | scoped ContactQuadratic output,scoped ContactQuadratic work,scoped ContactQuadratic term, |
| | | 89 | | scoped ContactQuadratic axial,scoped ContactQuadratic radial) |
| | | 90 | | { |
| | 402 | 91 | | work.Set(firstAxial);ContactQuadratic.Scale(work,secondAxial,axial); |
| | 603 | 92 | | work.Set(WideDirection3d.Dot(first,second));ContactQuadratic.Scale(work,q,radial);radial.Add(axial,-1); |
| | 402 | 93 | | ContactQuadratic.Scale(radial,q,work);ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(height)),t |
| | 201 | 94 | | ContactQuadratic.Scale(term,Signed576.ExtendValue(Signed192.Raw(height)),output); |
| | 402 | 95 | | ContactQuadratic.Scale(axial,Signed576.ExtendValue(Scale),work);ContactQuadratic.Scale(work,Signed576.ExtendValu |
| | 201 | 96 | | ContactQuadratic.Scale(term,Signed576.ExtendValue(Signed192.Raw(radius)),work); |
| | 402 | 97 | | ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(radius)),term);output.Add(term,-1); |
| | 201 | 98 | | } |
| | | 99 | | |
| | | 100 | | private static bool TryGetScaledConeFacePoint(in FixedTriangle triangle,in ScaledRigidFrame3d frame, |
| | | 101 | | Vector3d apex,Vector3d axis,Fixed64 height,Fixed64 radius,bool hasEdge, |
| | | 102 | | out FixedPointAnchor point,out Fixed64 axial) |
| | | 103 | | { |
| | 56 | 104 | | point=default;axial=default; |
| | 28 | 105 | | WideDirection3d normal=WideTriangleRelations.GetScaledTriangleLocalNormal(triangle,frame).Transform(frame.Geomet |
| | 29 | 106 | | if(normal.IsZero)return false; |
| | 27 | 107 | | var direction=new WideDirection3d(new WideAxis3(Signed320.ExtendValue(Signed192.Raw(axis.X)), |
| | 27 | 108 | | Signed320.ExtendValue(Signed192.Raw(axis.Y)),Signed320.ExtendValue(Signed192.Raw(axis.Z)))); |
| | 54 | 109 | | Signed832 normalSquare=normal.SquaredLength,alignment=WideDirection3d.Dot(normal,direction); |
| | 27 | 110 | | Signed832 plane=WideDirection3d.Dot(normal,GetScaledConeRelativePoint(frame.GetPoint(triangle.A),apex)); |
| | 27 | 111 | | Signed832 q=direction.SquaredLength; |
| | | 112 | | const int words=ScaledQueryWords; |
| | 54 | 113 | | Span<ulong> values=stackalloc ulong[18*words];Span<int> signs=stackalloc int[18]; |
| | 54 | 114 | | var a=ContactQuadratic.At(values,signs,0,words);var b=ContactQuadratic.At(values,signs,1,words); |
| | 54 | 115 | | var c=ContactQuadratic.At(values,signs,2,words);var p=ContactQuadratic.At(values,signs,3,words); |
| | 54 | 116 | | var work=ContactQuadratic.At(values,signs,4,words);var term=ContactQuadratic.At(values,signs,5,words); |
| | 54 | 117 | | var axisN=ContactQuadratic.At(values,signs,6,words);var axisD=ContactQuadratic.At(values,signs,7,words); |
| | 27 | 118 | | var ratio=ContactQuadratic.At(values,signs,8,words); |
| | 54 | 119 | | work.Set(normalSquare);ContactQuadratic.Scale(work,q,p); |
| | 81 | 120 | | work.Set(alignment);ContactQuadratic.Scale(work,alignment,term);p.Add(term,-1); |
| | 81 | 121 | | axisN.Set(plane);ContactQuadratic.Scale(axisN,Signed576.ExtendValue(Scale),work);work.CopyTo(axisN); |
| | 54 | 122 | | axisD.Set(alignment);ContactQuadratic.Scale(axisD,Signed576.ExtendValue(frame.Denominator),work); |
| | 27 | 123 | | ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(height)),axisD); |
| | 45 | 124 | | if(axisD.Signs[0]<0){axisN.MultiplySign(-1);axisD.MultiplySign(-1);} |
| | 27 | 125 | | bool crossesAxis=axisD.Signs[0]!=0&&axisN.Signs[0]>=0 |
| | 27 | 126 | | &&WideArithmetic.CompareMagnitudeEqualLength(axisN.Rational,axisD.Rational)<=0; |
| | 27 | 127 | | if(p.Signs[0]==0) |
| | | 128 | | { |
| | 18 | 129 | | if(hasEdge||!crossesAxis)return false; |
| | 6 | 130 | | return TryGetScaledConeAxisPoint(triangle,frame,apex,axis,alignment,plane,true,out point,out axial); |
| | | 131 | | } |
| | 45 | 132 | | work.Set(alignment);ContactQuadratic.Scale(work,alignment,term);ContactQuadratic.Scale(term,q,a); |
| | 15 | 133 | | ContactQuadratic.Scale(a,Signed576.ExtendValue(Signed192.Raw(height)),work); |
| | 15 | 134 | | ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(height)),a); |
| | 15 | 135 | | ContactQuadratic.Scale(p,Signed576.ExtendValue(Signed192.Raw(radius)),work); |
| | 15 | 136 | | ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(radius)),term); |
| | 45 | 137 | | ContactQuadratic.Scale(term,Signed576.ExtendValue(Scale),work);ContactQuadratic.Scale(work,Signed576.ExtendValue |
| | 30 | 138 | | ContactQuadratic.Scale(a,Signed576.ExtendValue(frame.Denominator),work);ContactQuadratic.Scale(work,Signed576.Ex |
| | 45 | 139 | | work.Set(alignment);ContactQuadratic.Scale(work,plane,term);ContactQuadratic.Scale(term,q,b); |
| | 30 | 140 | | ContactQuadratic.Scale(b,Signed576.ExtendValue(Scale),work);ContactQuadratic.Scale(work,Signed576.ExtendValue(Si |
| | 30 | 141 | | ContactQuadratic.Scale(term,Signed576.ExtendValue(frame.Denominator),b);b.MultiplySign(-1); |
| | 45 | 142 | | work.Set(plane);ContactQuadratic.Scale(work,plane,term);ContactQuadratic.Scale(term,q,c); |
| | 30 | 143 | | ContactQuadratic.Scale(c,Signed576.ExtendValue(Scale),work);ContactQuadratic.Scale(work,Signed576.ExtendValue(Sc |
| | 15 | 144 | | Signed832 one=Signed832.ExtendValue(Signed192.One); |
| | 17 | 145 | | if(!WideFiniteConeIntersection.TrySolveBoundedUnitPolynomial(a,b,c,default,one,one,one,Fixed64.MaxValue,out Fixe |
| | 13 | 146 | | Signed832 pValue=PackScaledCone832(p); |
| | | 147 | | bool contained; |
| | 13 | 148 | | if(!hasEdge) |
| | | 149 | | { |
| | 4 | 150 | | contained=crossesAxis |
| | 4 | 151 | | ?TryGetScaledConeAxisPoint(triangle,frame,apex,axis,alignment,plane,false,out _,out _) |
| | 4 | 152 | | :TryGetScaledConeStationaryPoint(triangle,frame,apex,axis,normal,normalSquare,alignment,plane,pValue,q,h |
| | | 153 | | } |
| | | 154 | | else |
| | | 155 | | { |
| | 9 | 156 | | int sign=WideFiniteConeIntersection.GetBorrowedPolynomialSignAtRationalParameter(a,b,c, |
| | 9 | 157 | | Signed832.ExtendValue(Signed192.Raw(entry)),Signed832.ExtendValue(MaximumParameter)); |
| | 9 | 158 | | Fixed64 lower=sign<0?Fixed64.FromRaw(entry.m_rawValue-1):entry; |
| | 9 | 159 | | Fixed64 upper=sign>0?Fixed64.FromRaw(entry.m_rawValue+1):entry; |
| | 9 | 160 | | contained=TryGetScaledConeStationaryPoint(triangle,frame,apex,axis,normal,normalSquare,alignment,plane,pValu |
| | 9 | 161 | | &&(lower==upper||TryGetScaledConeStationaryPoint(triangle,frame,apex,axis,normal,normalSquare,alignment, |
| | | 162 | | } |
| | 21 | 163 | | if(!contained||!TryGetScaledConeStationaryPoint(triangle,frame,apex,axis,normal,normalSquare,alignment,plane,pVa |
| | 10 | 164 | | work.Set(Signed576.ExtendValue(Signed192.Raw(height)));ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed1 |
| | 5 | 165 | | work.Set(Signed576.ExtendValue(MaximumParameter)); |
| | 5 | 166 | | axial=ContactQuadratic.RoundRatio(ratio,work,ReadOnlySpan<ulong>.Empty,0,height.m_rawValue); |
| | 5 | 167 | | return true; |
| | | 168 | | } |
| | | 169 | | |
| | | 170 | | private static bool TryGetScaledConeAxisPoint(in FixedTriangle triangle,in ScaledRigidFrame3d frame, |
| | | 171 | | Vector3d apex,Vector3d axis,Signed832 alignment,Signed832 plane,bool materialize, |
| | | 172 | | out FixedPointAnchor point,out Fixed64 axial) |
| | | 173 | | { |
| | | 174 | | const int words=ScaledQueryWords; |
| | 14 | 175 | | Span<ulong> values=stackalloc ulong[10*words];Span<int> signs=stackalloc int[10]; |
| | 14 | 176 | | var x=ContactQuadratic.At(values,signs,0,words);var y=ContactQuadratic.At(values,signs,1,words); |
| | 14 | 177 | | var z=ContactQuadratic.At(values,signs,2,words);var d=ContactQuadratic.At(values,signs,3,words); |
| | 7 | 178 | | var work=ContactQuadratic.At(values,signs,4,words); |
| | 14 | 179 | | work.Set(plane);ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(axis.X)),x); |
| | 7 | 180 | | ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(axis.Y)),y); |
| | 7 | 181 | | ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(axis.Z)),z); |
| | 14 | 182 | | work.Set(alignment);ContactQuadratic.Scale(work,Signed576.ExtendValue(frame.Denominator),d); |
| | 19 | 183 | | if(d.Signs[0]<0){d.MultiplySign(-1);x.MultiplySign(-1);y.MultiplySign(-1);z.MultiplySign(-1);} |
| | 14 | 184 | | point=default;axial=default; |
| | 9 | 185 | | if(!ContainsScaledConeFacePoint(triangle,frame,apex,x,y,z,d))return false; |
| | 6 | 186 | | if(!materialize)return true; |
| | 5 | 187 | | if(!QuadraticPointMaterialization.TryGetPointInFrame(apex,FixedQuaternion.Identity,x,y,z,d,ReadOnlySpan<ulong>.E |
| | 3 | 188 | | point=new FixedPointAnchor(apex,FixedQuaternion.Identity,local); |
| | 6 | 189 | | work.Set(plane);ContactQuadratic.Scale(work,Signed576.ExtendValue(Scale),x); |
| | 4 | 190 | | if(alignment.Sign<0)x.MultiplySign(-1); |
| | 3 | 191 | | axial=ContactQuadratic.RoundRatio(x,d,ReadOnlySpan<ulong>.Empty,0,long.MaxValue); |
| | 3 | 192 | | return true; |
| | | 193 | | } |
| | | 194 | | |
| | | 195 | | private static bool TryGetScaledConeStationaryPoint(in FixedTriangle triangle,in ScaledRigidFrame3d frame, |
| | | 196 | | Vector3d apex,Vector3d axis,in WideDirection3d normal,Signed832 normalSquare,Signed832 alignment, |
| | | 197 | | Signed832 plane,Signed832 p,Signed832 q,Fixed64 height,Fixed64 parameter,bool materialize,out FixedPointAnchor p |
| | | 198 | | { |
| | | 199 | | const int words=ScaledQueryWords; |
| | 44 | 200 | | Span<ulong> values=stackalloc ulong[16*words];Span<int> signs=stackalloc int[16]; |
| | 44 | 201 | | var x=ContactQuadratic.At(values,signs,0,words);var y=ContactQuadratic.At(values,signs,1,words); |
| | 44 | 202 | | var z=ContactQuadratic.At(values,signs,2,words);var d=ContactQuadratic.At(values,signs,3,words); |
| | 44 | 203 | | var work=ContactQuadratic.At(values,signs,4,words);var term=ContactQuadratic.At(values,signs,5,words); |
| | 44 | 204 | | var w=ContactQuadratic.At(values,signs,6,words);var v=ContactQuadratic.At(values,signs,7,words); |
| | 44 | 205 | | work.Set(p);ContactQuadratic.Scale(work,Signed576.ExtendValue(frame.Denominator),term); |
| | 44 | 206 | | ContactQuadratic.Scale(term,Signed576.ExtendValue(Scale),work);ContactQuadratic.Scale(work,Signed576.ExtendValue |
| | 176 | 207 | | for(int coordinate=0;coordinate<3;coordinate++) |
| | | 208 | | { |
| | 66 | 209 | | var output=coordinate==0?x:coordinate==1?y:z; |
| | 66 | 210 | | Signed576 n=coordinate==0?normal.X:coordinate==1?normal.Y:normal.Z; |
| | 132 | 211 | | work.Set(normalSquare);ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(axis[coordinate])),w) |
| | 198 | 212 | | work.Set(alignment);ContactQuadratic.Scale(work,n,term);w.Add(term,-1); |
| | 132 | 213 | | work.Set(q);ContactQuadratic.Scale(work,n,v); |
| | 198 | 214 | | work.Set(alignment);ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(axis[coordinate])),term) |
| | 132 | 215 | | ContactQuadratic.Scale(w,q,work);ContactQuadratic.Scale(work,Signed576.ExtendValue(Signed192.Raw(height)),te |
| | 132 | 216 | | ContactQuadratic.Scale(term,Signed576.ExtendValue(frame.Denominator),work);ContactQuadratic.Scale(work,Signe |
| | 132 | 217 | | ContactQuadratic.Scale(v,plane,work);ContactQuadratic.Scale(work,Signed576.ExtendValue(Scale),term); |
| | 132 | 218 | | ContactQuadratic.Scale(term,Signed576.ExtendValue(MaximumParameter),work);output.Add(work); |
| | | 219 | | } |
| | 22 | 220 | | point=default; |
| | 29 | 221 | | if(!ContainsScaledConeFacePoint(triangle,frame,apex,x,y,z,d))return false; |
| | 24 | 222 | | if(!materialize)return true; |
| | 7 | 223 | | if(!QuadraticPointMaterialization.TryGetPointInFrame(apex,FixedQuaternion.Identity,x,y,z,d,ReadOnlySpan<ulong>.E |
| | 10 | 224 | | point=new FixedPointAnchor(apex,FixedQuaternion.Identity,local);return true; |
| | | 225 | | } |
| | | 226 | | |
| | | 227 | | private static bool ContainsScaledConeFacePoint(in FixedTriangle triangle,in ScaledRigidFrame3d frame,Vector3d apex, |
| | | 228 | | scoped ContactQuadratic x,scoped ContactQuadratic y,scoped ContactQuadratic z,scoped ContactQuadratic denominato |
| | | 229 | | { |
| | | 230 | | const int words=ScaledQueryWords; |
| | 58 | 231 | | Span<ulong> values=stackalloc ulong[8*words];Span<int> signs=stackalloc int[8]; |
| | 58 | 232 | | var sum=ContactQuadratic.At(values,signs,0,words);var delta=ContactQuadratic.At(values,signs,1,words); |
| | 58 | 233 | | var term=ContactQuadratic.At(values,signs,2,words);var product=ContactQuadratic.At(values,signs,3,words); |
| | 29 | 234 | | WideDirection3d normal=WideTriangleRelations.GetScaledTriangleLocalNormal(triangle,frame); |
| | 196 | 235 | | for(int edge=0;edge<3;edge++) |
| | | 236 | | { |
| | 78 | 237 | | FixedSegment segment=triangle.GetEdge(edge); |
| | 78 | 238 | | WideDirection3d inward=WideDirection3d.Cross(normal,WideDirection3d.GetLocalEdge(frame,segment.Start,segment |
| | 156 | 239 | | WideDirection3d start=GetScaledConeRelativePoint(frame.GetPoint(segment.Start),apex);sum.Clear(); |
| | 624 | 240 | | for(int coordinate=0;coordinate<3;coordinate++) |
| | | 241 | | { |
| | 234 | 242 | | var point=coordinate==0?x:coordinate==1?y:z; |
| | 234 | 243 | | ContactQuadratic.Scale(point,Signed576.ExtendValue(frame.Denominator),delta); |
| | 468 | 244 | | ContactQuadratic.Scale(denominator,coordinate==0?start.X:coordinate==1?start.Y:start.Z,term);delta.Add(t |
| | 468 | 245 | | ContactQuadratic.Scale(delta,coordinate==0?inward.X:coordinate==1?inward.Y:inward.Z,product);sum.Add(pro |
| | | 246 | | } |
| | 87 | 247 | | if(sum.Signs[0]<0)return false; |
| | | 248 | | } |
| | 20 | 249 | | return true; |
| | | 250 | | } |
| | | 251 | | |
| | | 252 | | private static Signed832 PackScaledCone832(scoped ContactQuadratic value) |
| | | 253 | | { |
| | | 254 | | // Both callers pack nonnegative values: the positive axial cap and |
| | | 255 | | // the Gram minor |normal|²|axis|²-(normal.axis)². |
| | | 256 | | System.Diagnostics.Debug.Assert(value.Signs[0]>=0); |
| | 291 | 257 | | Span<ulong> data=stackalloc ulong[13];data.Clear();value.Rational[..WideArithmetic.GetActiveMagnitudeLength(valu |
| | 97 | 258 | | return new Signed832(data[12],data[11],data[10],data[9],data[8],data[7],data[6],data[5],data[4],data[3],data[2], |
| | | 259 | | } |
| | | 260 | | } |