Skip to content

Commit 14d3429

Browse files
Merge branch 'v0.2.0'
2 parents 666db99 + 9c9f3ea commit 14d3429

23 files changed

+1385
-224
lines changed

Package.resolved

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@
1919

2020
import PackageDescription
2121

22+
2223
let targets: [Target] = [
2324
.target(
2425
name: "kvGeometry",
25-
dependencies: [ .product(name: "kvKit", package: "kvKit-Swift") ]
26+
dependencies: [ .product(name: "kvKit", package: "kvKit.swift") ]
2627
),
2728
.target(
2829
name: "kvCSG",
2930
dependencies: [ "kvGeometry" ]
3031
),
31-
.testTarget(name: "kvGeometryTests", dependencies: [ "kvGeometry", .product(name: "kvTestKit", package: "kvKit-Swift") ]),
32+
.testTarget(name: "kvGeometryTests", dependencies: [ "kvGeometry", .product(name: "kvTestKit", package: "kvKit.swift") ]),
3233
]
3334

3435
let package = Package(
@@ -43,7 +44,7 @@ let package = Package(
4344
],
4445

4546
dependencies: [
46-
.package(url: "https://github.com/keyvariable/kvKit-Swift.git", from: "3.1.0"),
47+
.package(url: "https://github.com/keyvariable/kvKit.swift.git", from: "4.0.0"),
4748
],
4849

4950
targets: targets

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# kvGeometry
1+
# kvGeometry.swift
22

33
![Swift 5.2](https://img.shields.io/badge/swift-5.2-green.svg)
44
![Linux](https://img.shields.io/badge/os-linux-green.svg)
@@ -25,7 +25,7 @@ This package is completely crossplatform.
2525

2626
```swift
2727
dependencies: [
28-
.package(url: "https://github.com/keyvariable/kvGeometry.swift.git", from: "0.1.1"),
28+
.package(url: "https://github.com/keyvariable/kvGeometry.swift.git", from: "0.2.0"),
2929
]
3030
```
3131

Sources/kvGeometry/KvAABB3.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ public struct KvAABB3<Math : KvMathScope> {
294294
/// - Returns: An AABB produced applying scale to the receiver.
295295
///
296296
/// - Note: It's faster then apply an arbitrary transformation.
297-
@inlinable public func scaled(by scale: Vector) -> Self { Self(over: min * scale, max * scale) }
297+
@inlinable public func scaled(by scale: Vector) -> Self { Self(over: (min * scale) as Vector, (max * scale) as Vector) }
298298

299299

300300
/// Changes the receiver to enclose box produced as result of transformation of the receiver.

Sources/kvGeometry/KvAffineTransform3.swift

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public struct KvAffineTransform3<Math : KvMathScope> {
8181
/// Initializes product of rotation and scale transformations.
8282
@inlinable
8383
public init(quaternion: Math.Quaternion, scale: Vector) {
84-
let scale⁻¹ = 1 / scale
84+
let scale⁻¹ = (1.0 as Scalar) / scale
8585

8686
var m = Matrix(quaternion)
8787
var m⁻¹ = m.transpose
@@ -104,7 +104,7 @@ public struct KvAffineTransform3<Math : KvMathScope> {
104104
/// Initializes a scale transformation.
105105
@inlinable
106106
public init(scale: Vector) {
107-
let scale⁻¹ = 1 / scale
107+
let scale⁻¹ = (1.0 as Scalar) / scale
108108

109109
self.init(Matrix(diagonal: scale),
110110
Matrix(diagonal: scale⁻¹),
@@ -123,10 +123,11 @@ public struct KvAffineTransform3<Math : KvMathScope> {
123123

124124
/// - Returns: Scale component of given tranform matrix.
125125
///
126+
/// - Warning: Assuming the receiver has no shear component. Consider ``decompose(_:)`` method to extract scale from transformations having non-trivial shear component.
126127
/// - Note: If determinant of the matrix is negative then X scale element is negative and other elements are non-negative.
127128
@inlinable
128129
public static func scale(from m: Matrix) -> Vector {
129-
Vector(x: Math.length(m[0]) * (KvIsNotNegative(m.determinant) ? 1 : -1),
130+
Vector(x: Math.length(m[0]) * (KvIsNotNegative(m.determinant) ? (1.0 as Scalar) : (-1.0 as Scalar)),
130131
y: Math.length(m[1]),
131132
z: Math.length(m[2]))
132133
}
@@ -177,6 +178,54 @@ public struct KvAffineTransform3<Math : KvMathScope> {
177178

178179

179180

181+
// MARK: Decomposition
182+
183+
/// - Returns: Rotation, shear and scale components of the receiver.
184+
///
185+
/// See: ``decompose()``.
186+
public static func decompose(_ matrix: Matrix) -> (rotation: Matrix, shear: (xy: Scalar, xz: Scalar, yz: Scalar), scale: Vector) {
187+
var (m0, m1, m2) = matrix.columns
188+
189+
let sx = Math.length(m0)
190+
m0 /= sx
191+
192+
var sxy = Math.dot(m0, m1)
193+
m1 -= sxy * m0
194+
195+
let sy = Math.length(m1)
196+
do {
197+
let sy⁻¹ = (1.0 as Scalar) / sy
198+
m1 *= sy⁻¹
199+
sxy *= sy⁻¹
200+
}
201+
202+
var sxz = Math.dot(m0, m2)
203+
var syz = Math.dot(m1, m2)
204+
m2 -= sxz * m0
205+
m2 -= syz * m1
206+
207+
let sz = Math.length(m2)
208+
do {
209+
let sz⁻¹ = (1.0 as Scalar) / sz
210+
m2 *= sz⁻¹
211+
sxz *= sz⁻¹
212+
syz *= sz⁻¹
213+
}
214+
215+
return (rotation: .init(m0, m1, m2), shear: (xy: sxy, xz: sxz, yz: syz), scale: .init(sx, sy, sz))
216+
}
217+
218+
219+
/// - Returns: Rotation, shear and scale components of the receiver.
220+
///
221+
/// See: ``decompose(_:)``.
222+
@inlinable
223+
public func decompose() -> (rotation: Matrix, shear: (xy: Scalar, xz: Scalar, yz: Scalar), scale: Vector) {
224+
Self.decompose(matrix)
225+
}
226+
227+
228+
180229
// MARK: Operations
181230

182231
/// Transformed X basis vector.
@@ -203,6 +252,7 @@ public struct KvAffineTransform3<Math : KvMathScope> {
203252

204253
/// Scale component of the receiver.
205254
///
255+
/// - Warning: Assuming the receiver has no shear component. Consider ``decompose()`` method to extract scale from transformations having non-trivial shear component.
206256
/// - Note: If determinant of the matrix is negative then X scale element is negative and other elements are non-negative.
207257
@inlinable public var scale: Vector { KvAffineTransform3.scale(from: matrix) }
208258

Sources/kvGeometry/KvLine2.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//===----------------------------------------------------------------------===//
1717
//
1818
// KvLine2.swift
19-
// kvKit
19+
// kvGeometry
2020
//
2121
// Created by Svyatoslav Popov on 21.09.2022.
2222
//
@@ -157,15 +157,15 @@ public struct KvLine2<Math : KvMathScope> {
157157
public func y(x: Scalar) -> Scalar? {
158158
guard KvIsNonzero(normal.y) else { return nil }
159159

160-
return -(c + normal.x * x) as Scalar / normal.y
160+
return (-(c + normal.x * x)) as Scalar / normal.y
161161
}
162162

163163
/// - Returns: X coodinate where horizontal line at *y* intersects the receiver.
164164
@inlinable
165165
public func x(y: Scalar) -> Scalar? {
166166
guard KvIsNonzero(normal.x) else { return nil }
167167

168-
return -(c + normal.y * y) as Scalar / normal.x
168+
return (-(c + normal.y * y)) as Scalar / normal.x
169169
}
170170

171171

@@ -283,6 +283,8 @@ public struct KvLine2<Math : KvMathScope> {
283283
}
284284

285285

286+
// MARK: Transformations
287+
286288
/// Translates all the receiver's ponts by *offset*.
287289
///
288290
/// - Note: It's faster then apply an arbitrary transformation.

Sources/kvGeometry/KvLine3.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,16 @@ public struct KvLine3<Math : KvMathScope> {
117117

118118

119119
/// - Returns: The distance from the receiver to given coordinate.
120+
///
121+
/// See: ``distanceEpsArg(_:)``.
120122
@inlinable
121123
public func distance(to x: Coordinate) -> Scalar {
122124
Math.length(Math.cross(x - origin, front))
123125
}
124126

125127
/// - Returns: The distance from the receiver to given vertex.
128+
///
129+
/// See: ``distanceEpsArg(_:)``.
126130
@inlinable
127131
public func distance<V>(to v: V) -> Scalar
128132
where V : KvVertex3Protocol, V.Math == Math {
@@ -131,20 +135,30 @@ public struct KvLine3<Math : KvMathScope> {
131135

132136

133137
/// - Returns: A boolean value indicating whether the receiver contains given coordinate.
138+
///
139+
/// See: ``distanceEpsArg(_:)``.
134140
@inlinable
135141
public func contains(_ c: Coordinate) -> Bool {
136-
let c = c - origin
137-
return Math.isZero(Math.cross(front, c), eps: Math.epsArg(front).cross(Math.epsArg(c)).tolerance)
142+
Math.isZero(Math.cross(front, c - origin), eps: distanceEpsArg(c).tolerance)
138143
}
139144

140145
/// - Returns: A boolean value indicating whether the receiver contains given coordinate.
146+
///
147+
/// See: ``distanceEpsArg(_:)``.
141148
@inlinable
142149
public func contains<V>(_ v: V) -> Bool
143150
where V : KvVertex3Protocol, V.Math == Math {
144151
contains(v.coordinate)
145152
}
146153

147154

155+
/// - Returns: The tolerance argument for the distance calculation.
156+
@inlinable
157+
public func distanceEpsArg(_ c: Coordinate) -> Math.EpsArg3 {
158+
Math.epsArg(front).cross(Math.epsArg(c) - Math.epsArg(origin))
159+
}
160+
161+
148162
/// - Returns: Receivers coordinate having minimum distance to to given line or *nil* if the receiver and given line are parallel.
149163
///
150164
/// - See ``projection(of:)``.
@@ -171,6 +185,8 @@ public struct KvLine3<Math : KvMathScope> {
171185
@inlinable public func projection(of c: Coordinate) -> Coordinate { at(Math.dot((c - origin), front)) }
172186

173187

188+
// MARK: Transformations
189+
174190
/// - Returns: A line produced applying translation by *offset* to all the receiver's ponts.
175191
///
176192
/// - Note: It's faster then apply an arbitrary transformation.

Sources/kvGeometry/KvPlane3.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@ public struct KvPlane3<Math : KvMathScope> {
115115
@inlinable public var isDegenerate: Bool { Math.isZero(normal) }
116116

117117

118+
/// Length of the receiver's normal.
119+
/// E.g. it can be used to convert offsets of non-normalized planes to distances.
120+
///
121+
/// - Note: Use it as less as possible.
122+
/// - Note: There no need to use it when the receiver is normalized.
123+
@inlinable public var scale: Scalar { Math.length(normal) }
124+
125+
118126
/// A transformation matrix from z = 0 plane to the receiver.
119127
///
120128
/// - Note: Result is undefined when the receiver is degenerate.
@@ -169,7 +177,7 @@ public struct KvPlane3<Math : KvMathScope> {
169177
@inlinable public func signedOffset(to x: Coordinate) -> Scalar { at(x) }
170178

171179

172-
/// - Returns: The distance from the receiver to *x* divided by length of the normal.
180+
/// - Returns: The distance from the receiver to *x* scaled by length of the receiver's normal.
173181
@inlinable public func offset(to x: Coordinate) -> Scalar { abs(at(x)) }
174182

175183

0 commit comments

Comments
 (0)