1+ import Foundation
2+
3+ /// A size that describes width, height, and depth in a 3D coordinate system.
4+ @frozen public struct Size3D : Codable , Copyable , Equatable , Hashable , Sendable {
5+
6+ // MARK: - Creating a 3D size structure
7+
8+ /// Creates a size structure.
9+ @inline ( __always)
10+ public init ( ) {
11+ self . width = 0.0
12+ self . height = 0.0
13+ self . depth = 0.0
14+ }
15+
16+ /// Creates a size structure from the specified double-precision values.
17+ ///
18+ /// - Parameters:
19+ /// - width: A double-precision value that specifies the width.
20+ /// - height: A double-precision value that specifies the height.
21+ /// - depth: A double-precision value that specifies the depth.
22+ @inline ( __always)
23+ public init ( width: Double = 0 , height: Double = 0 , depth: Double = 0 ) {
24+ self . width = width
25+ self . height = height
26+ self . depth = depth
27+ }
28+
29+ /// Creates a size structure from the specified floating-point values.
30+ ///
31+ /// - Parameters:
32+ /// - width: A floating-point value that specifies the width.
33+ /// - height: A floating-point value that specifies the height.
34+ /// - depth: A floating-point value that specifies the depth.
35+ @inline ( __always)
36+ public init < T> ( width: T , height: T , depth: T ) where T : BinaryFloatingPoint {
37+ self . width = Double ( width)
38+ self . height = Double ( height)
39+ self . depth = Double ( depth)
40+ }
41+
42+ /// Creates a size structure from the specified vector.
43+ ///
44+ /// - Parameter xyz: A vector that contains the width, height, and depth values.
45+ @inline ( __always)
46+ public init ( _ xyz: Vector3D ) {
47+ ( width, height, depth) = ( xyz. x, xyz. y, xyz. z)
48+ }
49+
50+ // MARK: - Inspecting a 3D size’s properties
51+
52+ /// The width value.
53+ public let width : Double
54+
55+ /// The height value.
56+ public let height : Double
57+
58+ /// The depth value.
59+ public let depth : Double
60+
61+ /// Accesses the width, height, or depth value at the specified index.
62+ ///
63+ /// - Parameter index: The index of the value to access. Valid indices are 0, 1, and 2.
64+ /// - Returns: The width, height, or depth value at the specified index.
65+ /// - Complexity: O(1)
66+ @inline ( __always)
67+ public subscript( index: Int ) -> Double {
68+ get {
69+ switch index {
70+ case 0 : return width
71+ case 1 : return height
72+ case 2 : return depth
73+ default :
74+ fatalError ( " Index out of range. Valid indices are 0, 1, and 2. " )
75+ }
76+ }
77+ }
78+
79+ // MARK: - 3D size constants
80+
81+ /// The size structure with width, height, and depth values of one.
82+ public static let one = Size3D ( width: 1 , height: 1 , depth: 1 )
83+
84+ // MARK: - Creating derived 3D sizes
85+
86+ /// Returns the intersection of two sizes.
87+ ///
88+ /// - Parameter other: The size that the function compares against.
89+ /// - Returns: A new size that is the intersection of two sizes.
90+ @inline ( __always)
91+ public func intersection( _ other: Size3D ) -> Size3D ? {
92+ let newWidth = min ( self . width, other. width)
93+ let newHeight = min ( self . height, other. height)
94+ let newDepth = min ( self . depth, other. depth)
95+
96+ if newWidth >= 0 && newHeight >= 0 && newDepth >= 0 {
97+ return Size3D ( width: newWidth, height: newHeight, depth: newDepth)
98+ } else {
99+ return nil
100+ }
101+ }
102+ }
103+
104+ extension Size3D : ExpressibleByArrayLiteral {
105+
106+ /// Creates an instance initialized with the given elements.
107+ ///
108+ /// - Parameter elements: The elements of the array literal.
109+ @inline ( __always)
110+ public init ( arrayLiteral elements: Double ... ) {
111+ precondition ( elements. count == 3 , " Array literal must contain exactly three elements. " )
112+ ( width, height, depth) = ( elements [ 0 ] , elements [ 1 ] , elements [ 2 ] )
113+ }
114+ }
115+
116+ extension Size3D : AdditiveArithmetic {
117+
118+ // MARK: - Applying arithmetic operations
119+
120+ /// The zero size.
121+ public static let zero = Size3D ( )
122+
123+ /// Returns a size that’s the product of a size and a scalar value.
124+ ///
125+ /// - Parameters:
126+ /// - lhs: The left-hand-side value.
127+ /// - rhs: The right-hand-side scalar value.
128+ /// - Returns: The product of the size and the scalar.
129+ /// - Complexity: O(1)
130+ @inline ( __always)
131+ public static func * ( lhs: Size3D , rhs: Double ) -> Size3D {
132+ . init( width: lhs. width * rhs, height: lhs. height * rhs, depth: lhs. depth * rhs)
133+ }
134+
135+ /// Multiplies a size and a double-precision value, and stores the result in the left-hand-side variable.
136+ ///
137+ /// - Parameters:
138+ /// - lhs: The left-hand-side value.
139+ /// - rhs: The right-hand-side value.
140+ /// - Complexity: O(1)
141+ @inline ( __always)
142+ public static func *= ( lhs: inout Size3D , rhs: Double ) {
143+ lhs = lhs * rhs
144+ }
145+
146+ /// Adds two sizes and returns the result.
147+ ///
148+ /// - Parameters:
149+ /// - lhs: The first size.
150+ /// - rhs: The second size.
151+ /// - Returns: The sum of the two sizes.
152+ /// - Complexity: O(1)
153+ @inline ( __always)
154+ public static func + ( lhs: Size3D , rhs: Size3D ) -> Size3D {
155+ . init( width: lhs. width + rhs. width, height: lhs. height + rhs. height, depth: lhs. depth + rhs. depth)
156+ }
157+
158+ /// Adds the second size to the first size and stores the result in the first size.
159+ ///
160+ /// - Parameters:
161+ /// - lhs: The first size.
162+ /// - rhs: The second size.
163+ /// - Complexity: O(1)
164+ @inline ( __always)
165+ public static func += ( lhs: inout Size3D , rhs: Size3D ) {
166+ lhs = lhs + rhs
167+ }
168+
169+ /// Subtracts one size from another and returns the result.
170+ ///
171+ /// - Parameters:
172+ /// - lhs: The first size.
173+ /// - rhs: The second size.
174+ /// - Returns: The difference of the two sizes.
175+ /// - Complexity: O(1)
176+ @inline ( __always)
177+ public static func - ( lhs: Size3D , rhs: Size3D ) -> Size3D {
178+ . init( width: lhs. width - rhs. width, height: lhs. height - rhs. height, depth: lhs. depth - rhs. depth)
179+ }
180+
181+ /// Subtracts the second size from the first size and stores the result in the first size.
182+ ///
183+ /// - Parameters:
184+ /// - lhs: The first size.
185+ /// - rhs: The second size.
186+ /// - Complexity: O(1)
187+ @inline ( __always)
188+ public static func -= ( lhs: inout Size3D , rhs: Size3D ) {
189+ lhs = lhs - rhs
190+ }
191+
192+ /// Returns a size with each element divided by a scalar value.
193+ ///
194+ /// - Parameters:
195+ /// - lhs: The left-hand-side value.
196+ /// - rhs: The right-hand-side value.
197+ /// - Returns: The resulting size.
198+ /// - Complexity: O(1)
199+ @inline ( __always)
200+ public static func / ( lhs: Size3D , rhs: Double ) -> Size3D {
201+ . init( width: lhs. width / rhs, height: lhs. height / rhs, depth: lhs. depth / rhs)
202+ }
203+
204+ /// Divides each element of the size by a scalar value and stores the result in the left-hand-side variable.
205+ ///
206+ /// - Parameters:
207+ /// - lhs: The left-hand-side value.
208+ /// - rhs: The right-hand-side value.
209+ /// - Complexity: O(1)
210+ @inline ( __always)
211+ public static func /= ( lhs: inout Size3D , rhs: Double ) {
212+ lhs = lhs / rhs
213+ }
214+ }
215+
216+ extension Size3D : Primitive3D {
217+ // MARK: - Instance properties
218+
219+ /// A Boolean value that indicates whether the vector is finite.
220+ public var isFinite : Bool {
221+ width. isFinite && height. isFinite && depth. isFinite
222+ }
223+
224+ /// A Boolean value that indicates whether the vector contains any NaN values.
225+ public var isNaN : Bool {
226+ width. isNaN || height. isNaN || depth. isNaN
227+ }
228+
229+ /// A Boolean value that indicates whether the vector is zero.
230+ public var isZero : Bool {
231+ width == 0 && height == 0 && depth == 0
232+ }
233+
234+ // MARK: - Type properties
235+
236+ /// A size with infinite values.
237+ public static var infinity : Size3D {
238+ . init( width: . infinity, height: . infinity, depth: . infinity)
239+ }
240+
241+ // MARK: - Transforming primitives
242+
243+ // Applies an affine transform.
244+ ///
245+ /// - Parameter transform: The affine transform to apply.
246+ /// - Returns: A new transformed size.
247+ /// - Complexity: O(1)
248+ public func applying( _ transform: AffineTransform3D ) -> Size3D {
249+ fatalError ( " Size3D does not support applying affine transforms. " )
250+ }
251+ }
0 commit comments