Skip to content

Commit 6d47667

Browse files
committed
add math code
1 parent ea7e1d6 commit 6d47667

20 files changed

Lines changed: 5584 additions & 0 deletions

.gitignore

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,172 @@ DerivedData/
77
.swiftpm/config/registries.json
88
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
99
.netrc
10+
11+
# Xcode
12+
#
13+
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
14+
15+
## User settings
16+
xcuserdata/
17+
18+
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
19+
*.xcscmblueprint
20+
*.xccheckout
21+
22+
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
23+
build/
24+
DerivedData/
25+
*.moved-aside
26+
*.pbxuser
27+
!default.pbxuser
28+
*.mode1v3
29+
!default.mode1v3
30+
*.mode2v3
31+
!default.mode2v3
32+
*.perspectivev3
33+
!default.perspectivev3
34+
35+
## Obj-C/Swift specific
36+
*.hmap
37+
38+
## App packaging
39+
*.ipa
40+
*.dSYM.zip
41+
*.dSYM
42+
43+
## Playgrounds
44+
timeline.xctimeline
45+
playground.xcworkspace
46+
47+
# Swift Package Manager
48+
#
49+
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
50+
# Packages/
51+
# Package.pins
52+
# Package.resolved
53+
# *.xcodeproj
54+
#
55+
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
56+
# hence it is not needed unless you have added a package configuration file to your project
57+
# .swiftpm
58+
59+
.build/
60+
61+
# CocoaPods
62+
#
63+
# We recommend against adding the Pods directory to your .gitignore. However
64+
# you should judge for yourself, the pros and cons are mentioned at:
65+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
66+
#
67+
# Pods/
68+
#
69+
# Add this line if you want to avoid checking in source code from the Xcode workspace
70+
# *.xcworkspace
71+
72+
# Carthage
73+
#
74+
# Add this line if you want to avoid checking in source code from Carthage dependencies.
75+
# Carthage/Checkouts
76+
77+
Carthage/Build/
78+
79+
# Accio dependency management
80+
Dependencies/
81+
.accio/
82+
83+
# fastlane
84+
#
85+
# It is recommended to not store the screenshots in the git repo.
86+
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
87+
# For more information about the recommended setup visit:
88+
# https://docs.fastlane.tools/best-practices/source-control/#source-control
89+
90+
fastlane/report.xml
91+
fastlane/Preview.html
92+
fastlane/screenshots/**/*.png
93+
fastlane/test_output
94+
95+
# Code Injection
96+
#
97+
# After new code Injection tools there's a generated folder /iOSInjectionProject
98+
# https://github.com/johnno1962/injectionforxcode
99+
100+
iOSInjectionProject/
101+
102+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
103+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
104+
105+
# User-specific stuff
106+
.idea/**/workspace.xml
107+
.idea/**/tasks.xml
108+
.idea/**/usage.statistics.xml
109+
.idea/**/dictionaries
110+
.idea/**/shelf
111+
112+
# AWS User-specific
113+
.idea/**/aws.xml
114+
115+
# Generated files
116+
.idea/**/contentModel.xml
117+
118+
# Sensitive or high-churn files
119+
.idea/**/dataSources/
120+
.idea/**/dataSources.ids
121+
.idea/**/dataSources.local.xml
122+
.idea/**/sqlDataSources.xml
123+
.idea/**/dynamic.xml
124+
.idea/**/uiDesigner.xml
125+
.idea/**/dbnavigator.xml
126+
127+
# Gradle
128+
.idea/**/gradle.xml
129+
.idea/**/libraries
130+
131+
# Gradle and Maven with auto-import
132+
# When using Gradle or Maven with auto-import, you should exclude module files,
133+
# since they will be recreated, and may cause churn. Uncomment if using
134+
# auto-import.
135+
# .idea/artifacts
136+
# .idea/compiler.xml
137+
# .idea/jarRepositories.xml
138+
# .idea/modules.xml
139+
# .idea/*.iml
140+
# .idea/modules
141+
# *.iml
142+
# *.ipr
143+
144+
# CMake
145+
cmake-build-*/
146+
147+
# Mongo Explorer plugin
148+
.idea/**/mongoSettings.xml
149+
150+
# File-based project format
151+
*.iws
152+
153+
# IntelliJ
154+
out/
155+
156+
# mpeltonen/sbt-idea plugin
157+
.idea_modules/
158+
159+
# JIRA plugin
160+
atlassian-ide-plugin.xml
161+
162+
# Cursive Clojure plugin
163+
.idea/replstate.xml
164+
165+
# SonarLint plugin
166+
.idea/sonarlint/
167+
168+
# Crashlytics plugin (for Android Studio and IntelliJ)
169+
com_crashlytics_export_strings.xml
170+
crashlytics.properties
171+
crashlytics-build.properties
172+
fabric.properties
173+
174+
# Editor-based Rest Client
175+
.idea/httpRequests
176+
177+
# Android studio 3.1+ serialized cache file
178+
.idea/caches/build_file_checksums.ser

Sources/Math/BoundingBox.swift

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
// Copyright (c) 2022 Feng Yang
2+
//
3+
// I am making my contributions/submissions to this project solely in my
4+
// personal capacity and am not conveying any rights to any intellectual
5+
// property of any third parties.
6+
7+
import Foundation
8+
9+
/// Axis Aligned Bound Box (AABB).
10+
public struct BoundingBox {
11+
private var m_Center = Vector3()
12+
private var m_Extents = Vector3()
13+
14+
/// The center of the bounding box.
15+
public var center: Vector3 {
16+
get {
17+
m_Center
18+
}
19+
set {
20+
m_Center = newValue
21+
}
22+
}
23+
24+
/// The total size of the box. This is always twice as large as the extents.
25+
public var size: Vector3 {
26+
get {
27+
m_Extents * 2
28+
}
29+
set {
30+
m_Extents = newValue * 0.5
31+
}
32+
}
33+
34+
/// The extents of the Bounding Box. This is always half of the size of the Bounds.
35+
public var extents: Vector3 {
36+
get {
37+
m_Extents
38+
}
39+
set {
40+
m_Extents = newValue
41+
}
42+
}
43+
44+
/// The minimal point of the box. This is always equal to center-extents.
45+
public var min: Vector3 {
46+
get {
47+
center - extents
48+
}
49+
set {
50+
setMinMax(newValue, max)
51+
}
52+
}
53+
54+
/// The maximal point of the box. This is always equal to center+extents.
55+
public var max: Vector3 {
56+
get {
57+
center + extents
58+
}
59+
set {
60+
setMinMax(min, newValue)
61+
}
62+
}
63+
64+
/// Constructor of BoundingBox.
65+
/// - Parameters:
66+
/// - min: The minimum point of the box
67+
/// - max: The maximum point of the box
68+
public init(_ min: Vector3? = nil, _ max: Vector3? = nil) {
69+
if let min {
70+
self.min = min
71+
}
72+
if let max {
73+
self.max = max
74+
}
75+
}
76+
77+
/// Sets the bounds to the min and max value of the box.
78+
public mutating func setMinMax(_ min: Vector3, _ max: Vector3) {
79+
extents = (max - min) * 0.5
80+
center = min + extents;
81+
}
82+
}
83+
84+
//MARK: - Static Methods
85+
86+
extension BoundingBox {
87+
/// Calculate a bounding box from the center point and the extent of the bounding box.
88+
/// - Parameters:
89+
/// - center: The center point
90+
/// - extent: The extent of the bounding box
91+
/// - Returns: The calculated bounding box
92+
public static func fromCenterAndExtent(center: Vector3, extent: Vector3) -> BoundingBox {
93+
BoundingBox(center - extent, center + extent)
94+
}
95+
96+
/// Calculate a bounding box that fully contains the given points.
97+
/// - Parameters:
98+
/// - points: The given points
99+
/// - Returns: The calculated bounding box
100+
public static func fromPoints(points: [Vector3]) -> BoundingBox {
101+
if (points.count == 0) {
102+
fatalError("points must be array and length must > 0")
103+
}
104+
105+
var out = BoundingBox(Vector3(Float.greatestFiniteMagnitude, Float.greatestFiniteMagnitude, Float.greatestFiniteMagnitude),
106+
Vector3(-Float.greatestFiniteMagnitude, -Float.greatestFiniteMagnitude, -Float.greatestFiniteMagnitude))
107+
for point in points {
108+
out.setMinMax(Vector3.min(left: out.min, right: point),
109+
Vector3.max(left: out.max, right: point))
110+
}
111+
return out
112+
}
113+
114+
/// Calculate a bounding box from a given sphere.
115+
/// - Parameters:
116+
/// - sphere: The given sphere
117+
/// - Returns: The calculated bounding box
118+
public static func fromSphere(sphere: BoundingSphere) -> BoundingBox {
119+
let center = sphere.center
120+
let radius = sphere.radius
121+
return BoundingBox(Vector3(center.x - radius, center.y - radius, center.z - radius),
122+
Vector3(center.x + radius, center.y + radius, center.z + radius))
123+
}
124+
125+
/// Transform a bounding box.
126+
/// - Parameters:
127+
/// - source: The original bounding box
128+
/// - matrix: The transform to apply to the bounding box
129+
/// - Returns: The transformed bounding box
130+
public static func transform(source: BoundingBox, matrix: Matrix) -> BoundingBox {
131+
// https://zeux.io/2010/10/17/aabb-from-obb-with-component-wise-abs/
132+
var center = source.getCenter()
133+
var extent = source.getExtent()
134+
center = Vector3.transformCoordinate(v: center, m: matrix)
135+
136+
let x = extent.x
137+
let y = extent.y
138+
let z = extent.z
139+
140+
extent = Vector3(abs(x * matrix.elements.columns.0[0]) + abs(y * matrix.elements.columns.1[0]) + abs(z * matrix.elements.columns.2[0]),
141+
abs(x * matrix.elements.columns.0[1]) + abs(y * matrix.elements.columns.1[1]) + abs(z * matrix.elements.columns.2[1]),
142+
abs(x * matrix.elements.columns.0[2]) + abs(y * matrix.elements.columns.1[2]) + abs(z * matrix.elements.columns.2[2]))
143+
144+
// set min、max
145+
return BoundingBox(center - extent, center + extent)
146+
}
147+
148+
/// Calculate a bounding box that is as large as the total combined area of the two specified boxes.
149+
/// - Parameters:
150+
/// - box1: The first box to merge
151+
/// - box2: The second box to merge
152+
/// - Returns: The merged bounding box
153+
public static func merge(box1: BoundingBox, box2: BoundingBox) -> BoundingBox {
154+
BoundingBox(Vector3.min(left: box1.min, right: box2.min), Vector3.max(left: box1.max, right: box2.max))
155+
}
156+
}
157+
158+
extension BoundingBox {
159+
/// Get the center point of this bounding box.
160+
/// - Returns: The center point of this bounding box
161+
public func getCenter() -> Vector3 {
162+
(min + max) * 0.5
163+
}
164+
165+
/// Get the extent of this bounding box.
166+
/// - Returns: The extent of this bounding box
167+
public func getExtent() -> Vector3 {
168+
(max - min) * 0.5
169+
}
170+
171+
/// Get the eight corners of this bounding box.
172+
/// - Returns: An array of points representing the eight corners of this bounding box
173+
public func getCorners() -> [Vector3] {
174+
let minX = min.x
175+
let minY = min.y
176+
let minZ = min.z
177+
let maxX = max.x
178+
let maxY = max.y
179+
let maxZ = max.z
180+
181+
// The array length is less than 8 to make up
182+
var out = Array<Vector3>(repeating: Vector3(), count: 8)
183+
_ = out[0].set(x: minX, y: maxY, z: maxZ)
184+
_ = out[1].set(x: maxX, y: maxY, z: maxZ)
185+
_ = out[2].set(x: maxX, y: minY, z: maxZ)
186+
_ = out[3].set(x: minX, y: minY, z: maxZ)
187+
_ = out[4].set(x: minX, y: maxY, z: minZ)
188+
_ = out[5].set(x: maxX, y: maxY, z: minZ)
189+
_ = out[6].set(x: maxX, y: minY, z: minZ)
190+
_ = out[7].set(x: minX, y: minY, z: minZ)
191+
192+
return out
193+
}
194+
195+
/// Transform a bounding box.
196+
/// - Parameter matrix: The transform to apply to the bounding box
197+
/// - Returns: The transformed bounding box
198+
public mutating func transform(matrix: Matrix) -> BoundingBox {
199+
self = BoundingBox.transform(source: self, matrix: matrix)
200+
return self
201+
}
202+
}
203+
204+
public typealias Bounds = BoundingBox
205+
206+
extension BoundingBox: Codable {
207+
}

0 commit comments

Comments
 (0)