55 * http://stregasgate.com
66 */
77
8+ public typealias Triangle2f = Triangle2n < Float32 >
9+ public typealias Triangle2d = Triangle2n < Float64 >
10+
811@frozen
912public struct Triangle2n < Scalar: Vector2n . ScalarType & FloatingPoint > {
1013 /// The cartesian position of the triangle's first point.
@@ -19,13 +22,103 @@ public struct Triangle2n<Scalar: Vector2n.ScalarType & FloatingPoint> {
1922 - parameter p2: The cartesian position of the triangle's second point.
2023 - parameter p3: The cartesian position of the triangle's third point.
2124 */
22- public init ( _ p1: Position2n < Scalar > , p2: Position2n < Scalar > , p3: Position2n < Scalar > ) {
25+ public init ( p1: Position2n < Scalar > , p2: Position2n < Scalar > , p3: Position2n < Scalar > ) {
2326 self . p1 = p1
2427 self . p2 = p2
2528 self . p3 = p3
2629 }
2730}
2831
32+ public extension Triangle2n where Scalar: ExpressibleByFloatLiteral {
33+ var center : Position2n < Scalar > {
34+ return Position2n < Scalar > ( x: ( p1. x + p2. x + p3. x) / 3.0 , y: ( p1. y + p2. y + p3. y) / 3.0 )
35+ }
36+ }
37+
38+ public extension Triangle2n {
39+ @inlinable
40+ func contains( _ position: Position2n < Scalar > ) -> Bool where Scalar: ExpressibleByFloatLiteral {
41+ let pa = self . p1
42+ let pb = self . p2
43+ let pc = self . p3
44+
45+ let e10 = pb - pa
46+ let e20 = pc - pa
47+ let a = e10. dot ( e10)
48+ let b = e10. dot ( e20)
49+ let c = e20. dot ( e20)
50+ let ac_bb = ( a * c) - ( b * b)
51+ let vp = Position2n ( x: position. x - pa. x, y: position. y - pa. y)
52+ let d = vp. dot ( e10)
53+ let e = vp. dot ( e20)
54+ let x = ( d * c) - ( e * b)
55+ let y = ( e * a) - ( d * b)
56+ let z = x + y - ac_bb
57+
58+ return z < 0.0 && x >= 0.0 && y >= 0.0
59+ }
60+
61+ /**
62+ Locates a position on the surface of this triangle that is as close to the given point as possible.
63+ - parameter position: A point in space to use as an reference
64+ - returns: The point on the triangle's surface that is nearest to `p`
65+ */
66+ func nearestSurfacePosition( to position: Position2n < Scalar > ) -> Position2n < Scalar > where Scalar: ExpressibleByFloatLiteral {
67+ let a = self . p1
68+ let b = self . p2
69+ let c = self . p3
70+ let p = position
71+
72+ // Check if P in vertex region outside A
73+ let ab = b - a
74+ let ac = c - a
75+ let ap = p - a
76+
77+ let d1 = ab. dot ( ap)
78+ let d2 = ac. dot ( ap)
79+ if d1 <= 0 && d2 <= 0 {
80+ return a // barycentric coordinates (1,0,0)
81+ }
82+ // Check if P in vertex region outside B
83+ let bp = p - b
84+ let d3 = ab. dot ( bp)
85+ let d4 = ac. dot ( bp)
86+ if d3 >= 0 && d4 <= d3 {
87+ return b // barycentric coordinates (0,1,0)
88+ }
89+ // Check if P in edge region of AB, if so return projection of P onto AB
90+ let vc = d1 * d4 - d3 * d2
91+ if vc <= 0 && d1 >= 0 && d3 <= 0 {
92+ let v = d1 / ( d1 - d3)
93+ return a + ab * v // barycentric coordinates (1-v,v,0)
94+ }
95+ // Check if P in vertex region outside C
96+ let cp = p - c
97+ let d5 = ab. dot ( cp)
98+ let d6 = ac. dot ( cp)
99+ if d6 >= 0 && d5 <= d6 {
100+ return c // barycentric coordinates (0,0,1)
101+ }
102+ // Check if P in edge region of AC, if so return projection of P onto AC
103+ let vb = d5 * d2 - d1 * d6
104+ if vb <= 0 && d2 >= 0 && d6 <= 0 {
105+ let w = d2 / ( d2 - d6)
106+ return a + ac * w // barycentric coordinates (1-w,0,w)
107+ }
108+ // Check if P in edge region of BC, if so return projection of P onto BC
109+ let va = d3 * d6 - d5 * d4
110+ if va <= 0 && ( d4 - d3) >= 0 && ( d5 - d6) >= 0 {
111+ let w = ( d4 - d3) / ( ( d4 - d3) + ( d5 - d6) )
112+ return b + ( c - b) * w // barycentric coordinates (0,1-w,w)
113+ }
114+ // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
115+ let denom = 1.0 / ( va + vb + vc)
116+ let v = vb * denom
117+ let w = vc * denom
118+ return a + ab * v + ac * w //=u*a+v*b+w*c,u=va*denom=1.0f-v-w
119+ }
120+ }
121+
29122// MARK: - Barycentric
30123public extension Triangle2n where Scalar: ExpressibleByFloatLiteral {
31124 /**
0 commit comments