-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathExclusiveDisjunction2Parametric.swift
75 lines (66 loc) · 2.68 KB
/
ExclusiveDisjunction2Parametric.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
import Geometria
/// An exclusive-disjunction, symmetric difference, or disjunctive union boolean
/// parametric that outputs the non-shared area between two or more geometries.
public struct ExclusiveDisjunction2Parametric<Vector: Vector2Real & Hashable>: Boolean2Parametric {
public typealias Contour = Parametric2Contour<Vector>
public let contours: [Contour]
public let tolerance: Scalar
public init<T1: ParametricClip2Geometry, T2: ParametricClip2Geometry>(
_ lhs: T1,
_ rhs: T2,
tolerance: T1.Scalar = .leastNonzeroMagnitude
) where T1.Vector == T2.Vector, T1.Vector == Vector, T1.Vector: Hashable {
self.init(
contours: lhs.allContours() + rhs.allContours(),
tolerance: tolerance
)
}
public init(
contours: [Contour],
tolerance: Scalar = .leastNonzeroMagnitude
) {
self.contours = contours
self.tolerance = tolerance
}
@inlinable
public func allContours() -> [Contour] {
// An exclusive disjunction can be expressed as a union followed by a
// subtraction of the intersection
let union = union(tolerance: tolerance, contours: self.contours)
let intersection = intersection(tolerance: tolerance, contours: self.contours)
return subtraction(tolerance: tolerance, union, [intersection]).allContours()
}
@inlinable
public static func exclusiveDisjunction<T1: ParametricClip2Geometry, T2: ParametricClip2Geometry>(
tolerance: Vector.Scalar = .leastNonzeroMagnitude,
_ lhs: T1,
_ rhs: T2
) -> Compound2Parametric<Vector> where T1.Vector == T2.Vector, T1.Vector == Vector, T1.Vector: Hashable {
let op = Self(lhs, rhs, tolerance: tolerance)
return .init(contours: op.allContours())
}
}
/// Performs an exclusive disjunction operation across all given parametric
/// geometries.
///
/// - precondition: `shapes` is not empty.
@inlinable
public func exclusiveDisjunction<Vector: Hashable>(
tolerance: Vector.Scalar = .leastNonzeroMagnitude,
_ shapes: [some ParametricClip2Geometry<Vector>]
) -> Compound2Parametric<Vector> {
return exclusiveDisjunction(
tolerance: tolerance,
contours: shapes.flatMap({ $0.allContours() })
)
}
/// Performs an exclusive disjunction operation across all given parametric
/// geometries.
@inlinable
public func exclusiveDisjunction<Vector: Hashable>(
tolerance: Vector.Scalar = .leastNonzeroMagnitude,
contours: [Parametric2Contour<Vector>]
) -> Compound2Parametric<Vector> {
let op = ExclusiveDisjunction2Parametric(contours: contours, tolerance: tolerance)
return Compound2Parametric(contours: op.allContours())
}