-
Notifications
You must be signed in to change notification settings - Fork 1
/
Triangle.swift
124 lines (108 loc) · 3.39 KB
/
Triangle.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/// Represents a [triangle] as a trio of N-dimensional vectors which describe a
/// 2-dimensional enclosed surface on an euclidean space.
///
/// [line segment]: https://en.wikipedia.org/wiki/Triangle
public struct Triangle<Vector: VectorType>: GeometricType {
/// Convenience for `Vector.Scalar`
public typealias Scalar = Vector.Scalar
/// The first point of this triangle.
public var a: Vector
/// The second point of this triangle.
public var b: Vector
/// The third point of this triangle.
public var c: Vector
@_transparent
public init(a: Vector, b: Vector, c: Vector) {
self.a = a
self.b = b
self.c = c
}
}
public extension Triangle {
/// Returns a line segment for the edge between the points ``a`` `->` ``b``.
@_transparent
var lineAB: LineSegment<Vector> {
.init(start: a, end: b)
}
/// Returns a line segment for the edge between the points ``a`` `->` ``c``.
@_transparent
var lineAC: LineSegment<Vector> {
.init(start: a, end: c)
}
/// Returns a line segment for the edge between the points ``b`` `->` ``c``.
@_transparent
var lineBC: LineSegment<Vector> {
.init(start: b, end: c)
}
/// Returns a line segment for the edge between the points ``b`` `->` ``a``.
@_transparent
var lineBA: LineSegment<Vector> {
.init(start: b, end: a)
}
/// Returns a line segment for the edge between the points ``c`` `->` ``a``.
@_transparent
var lineCA: LineSegment<Vector> {
.init(start: c, end: a)
}
/// Returns a line segment for the edge between the points ``c`` `->` ``b``.
@_transparent
var lineCB: LineSegment<Vector> {
.init(start: c, end: b)
}
}
extension Triangle: BoundableType where Vector: VectorComparable {
@_transparent
public var bounds: AABB<Vector> {
AABB(of: a, b, c)
}
}
public extension Triangle where Vector: VectorDivisible {
/// Returns the geometric center of this triangle.
///
/// Equivalent to the arithmetic mean of the three points of this triangle:
///
/// ```swift
/// (a + b + c) / 3
/// ```
@_transparent
var center: Vector {
let sum: Vector = a + b + c
return sum / 3
}
}
public extension Triangle where Vector: VectorFloatingPoint {
/// Returns the positive area of this triangle.
///
/// Performs the following operation:
///
/// ```
/// 1÷2 √(|AB|² |AC|² - (AB • AC)²)
/// ```
///
/// Where `AB` is the vector going from ``a`` to ``b``, and `AC` from ``a``
/// to ``c``:
///
/// ```swift
/// let AB = a - b
/// let AC = a - c
/// ```
///
/// (the area of the triangle is half of the area of the [parallelogram]
/// formed by the vectors AB / AC on the plane of those vertices).
///
/// Triangles with internal angles of 0° or 180° have an area of zero.
///
/// [parallelogram]: https://en.wikipedia.org/wiki/Parallelogram
@inlinable
var area: Scalar {
let ab = lineAB
let ac = lineAC
let abL = ab.lengthSquared
let acL = ac.lengthSquared
let abacD = ab.lineSlope.dot(ac.lineSlope) // cspell: disable-line
let resL: Scalar = abL * acL
let resR: Scalar = (abacD * abacD) // cspell: disable-line
let res: Scalar = resL - resR
return res.squareRoot() / 2
}
}