Skip to content

Commit

Permalink
Renaming Convex2Convex2Intersection to ClosedShape2Intersection
Browse files Browse the repository at this point in the history
  • Loading branch information
LuizZak committed Jul 2, 2024
1 parent 244fb72 commit 543a658
Show file tree
Hide file tree
Showing 8 changed files with 316 additions and 118 deletions.
2 changes: 1 addition & 1 deletion Sources/Geometria/2D/Circle2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extension Circle2: Convex2Type where Vector: Vector2FloatingPoint {
///
/// If the circles are coincident on the same center, and have the same radius,
/// the result is `.noIntersection`.
public func intersection(with other: Self) -> Convex2Convex2Intersection<Vector> {
public func intersection(with other: Self) -> ClosedShape2Intersection<Vector> {
func pointNormal(_ p: Vector, normal: Vector) -> PointNormal<Vector> {
.init(point: p, normal: normal)
}
Expand Down
132 changes: 132 additions & 0 deletions Sources/Geometria/2D/ClosedShape2Intersection.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/// The result of a intersection test against two 2-dimensional closed shapes.
public enum ClosedShape2Intersection<Vector: Vector2FloatingPoint> {
/// Represents the case where the convex's boundaries are completely contained
/// within the bounds of the other convex shape.
case contained

/// Represents the case where the other convex's boundaries are completely
/// contained within the bounds of the first convex shape.
///
/// Is the diametrical opposite of `.contained`.
case contains

/// Represents the case where the convex crosses the bounds of the convex
/// shape on a single vertex, or tangentially, in case of spheroids.
case singlePoint(PointNormal<Vector>)

/// A sequence of one or more intersection pairs of points that represent
/// the entrance and exit points of the intersection in relation to one of
/// the convexes.
case pairs([Pair])

/// Represents the case where no intersection occurs at any point.
case noIntersection

/// Convenience for `.pairs([.init(enter: p1, exit: p2)])`.
@inlinable
public static func twoPoints(
_ p1: PointNormal<Vector>,
_ p2: PointNormal<Vector>
) -> Self {
.pairs([
.init(enter: p1, exit: p2)
])
}

/// Returns a new ``ClosedShape2Intersection`` where any ``PointNormal`` value
/// is mapped by a provided closure before being stored back into the same
/// enum case and returned.
public func mappingPointNormals(
_ mapper: (PointNormal<Vector>, PointNormalKind) -> PointNormal<Vector>
) -> Self {

switch self {
case .contained:
return .contained

case .contains:
return .contains

case .noIntersection:
return .noIntersection

case .singlePoint(let pointNormal):
return .singlePoint(mapper(pointNormal, .singlePoint))

case .pairs(let pairs):
return .pairs(pairs.enumerated().map({ pair in
.init(
enter: mapper(pair.element.enter, .pairEnter(index: pair.offset)),
exit: mapper(pair.element.exit, .pairExit(index: pair.offset))
)
}))
}
}

/// Returns a new ``ClosedShape2Intersection`` where any ``PointNormal`` value
/// is replaced by a provided closure before being stored back into the same
/// enum case and returned.
public func replacingPointNormals<NewVector: VectorType>(
_ mapper: (PointNormal<Vector>, PointNormalKind) -> PointNormal<NewVector>
) -> ClosedShape2Intersection<NewVector> {

switch self {
case .contained:
return .contained

case .contains:
return .contains

case .noIntersection:
return .noIntersection

case .singlePoint(let pointNormal):
return .singlePoint(mapper(pointNormal, .singlePoint))

case .pairs(let pairs):
return .pairs(pairs.enumerated().map { pair in
.init(
enter: mapper(pair.element.enter, .pairEnter(index: pair.offset)),
exit: mapper(pair.element.exit, .pairExit(index: pair.offset))
)
})
}
}

/// A pair of entrance/exit intersection points.
///
/// The definition of entrance/exit is dependant on the shapes intersected,
/// and the only requirement is that within the same `ClosedShape2Intersection`,
/// each pair is expected to be connectable entrance-to-exit with its
/// succeeding pair.
public struct Pair {
/// The entrance point of the intersection.
public var enter: PointNormal<Vector>

/// The exit point of the intersection.
public var exit: PointNormal<Vector>

public init(enter: PointNormal<Vector>, exit: PointNormal<Vector>) {
self.enter = enter
self.exit = exit
}
}

/// Parameter passed along point normals in ``mappingPointNormals(_:)`` and
/// ``replacingPointNormals(_:)`` to specify to the closure which kind of point
/// normal was provided.
public enum PointNormalKind {
case singlePoint
case twoPointsFirst
case twoPointsSecond
case points(index: Int)
case pairEnter(index: Int)
case pairExit(index: Int)
}
}

extension ClosedShape2Intersection.Pair: Equatable where Vector: Equatable { }
extension ClosedShape2Intersection.Pair: Hashable where Vector: Hashable { }

extension ClosedShape2Intersection: Equatable where Vector: Equatable { }
extension ClosedShape2Intersection: Hashable where Vector: Hashable { }
96 changes: 0 additions & 96 deletions Sources/Geometria/2D/Convex2Convex2Intersection.swift

This file was deleted.

28 changes: 14 additions & 14 deletions Sources/TestCommons/Assertions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,12 @@ public func assertEqual<T>(

#endif // #if ENABLE_SIMD && canImport(simd)

// MARK: Convex2Convex2Intersection equality
// MARK: ClosedShape2Intersection equality

@discardableResult
public func assertEqual<T: Vector2FloatingPoint>(
_ actual: Convex2Convex2Intersection<T>,
_ expected: Convex2Convex2Intersection<T>,
_ actual: ClosedShape2Intersection<T>,
_ expected: ClosedShape2Intersection<T>,
file: StaticString = #file,
line: UInt = #line
) -> Bool {
Expand All @@ -224,6 +224,14 @@ public func assertEqual<T: Vector2FloatingPoint>(
)
"""
}
let printPair: (ClosedShape2Intersection<T>.Pair) -> String = { pair in
"""
.init(
enter: \(printPointNormal(pair.enter)),
exit: \(printPointNormal(pair.exit)),
)
"""
}

var buffer = ""

Expand All @@ -244,18 +252,10 @@ public func assertEqual<T: Vector2FloatingPoint>(
)
"""

case .points(let points) where points.count == 2:
buffer = """
.twoPoints(
\(printPointNormal(points[0])),
\(printPointNormal(points[1]))
)
"""

case .points(let points):
case .pairs(let points):
buffer = """
.points(
\(points.map(printPointNormal).joined(separator: ",\n"))
.pairs(
\(points.map(printPair).joined(separator: ",\n"))
)
"""
}
Expand Down
27 changes: 23 additions & 4 deletions Sources/TestCommons/P5Printer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ public class P5Printer {
addDrawLine("")
}

func add<V: Vector2Type>(_ polygon: LinePolygon<V>, style: Style? = nil, file: StaticString = #file, line: UInt = #line) where V.Scalar: CustomStringConvertible {
addFileAndLineComment(file: file, line: line)
addStyleSet(style ?? styling.geometry)
for lineGeom in polygon.lineSegments() {
addDrawLine("line(\(vec2String(lineGeom.a)), \(vec2String(lineGeom.b)))")
}
addDrawLine("")
}

func add<Vector: Vector3Type>(_ ray: DirectionalRay3<Vector>, style: Style? = nil, file: StaticString = #file, line: UInt = #line) where Vector.Scalar: FloatingPoint & CustomStringConvertible {
is3D = true

Expand All @@ -102,6 +111,15 @@ public class P5Printer {
addDrawLine("")
}

func add<V: Vector3Type>(_ polygon: LinePolygon<V>, style: Style? = nil, file: StaticString = #file, line: UInt = #line) where V.Scalar: CustomStringConvertible {
addFileAndLineComment(file: file, line: line)
addStyleSet(style ?? styling.geometry)
for lineGeom in polygon.lineSegments() {
addDrawLine("line(\(vec3String(lineGeom.a)), \(vec3String(lineGeom.b)))")
}
addDrawLine("")
}

func add<V: Vector2Type>(_ result: ConvexLineIntersection<V>, style: Style? = nil, file: StaticString = #file, line: UInt = #line) where V.Scalar: CustomStringConvertible {
switch result {
case .contained, .noIntersection:
Expand All @@ -114,17 +132,18 @@ public class P5Printer {
}
}

func add<V: Vector2Type>(_ result: Convex2Convex2Intersection<V>, style: Style? = nil, file: StaticString = #file, line: UInt = #line) where V.Scalar: CustomStringConvertible {
func add<V: Vector2Type>(_ result: ClosedShape2Intersection<V>, style: Style? = nil, file: StaticString = #file, line: UInt = #line) where V.Scalar: CustomStringConvertible {
switch result {
case .contained, .contains, .noIntersection:
break

case .singlePoint(let pn):
add(pn, style: style, file: file, line: line)

case .points(let points):
for point in points {
add(point, style: style, file: file, line: line)
case .pairs(let pairs):
for pair in pairs {
add(pair.enter, style: style, file: file, line: line)
add(pair.exit, style: style, file: file, line: line)
}
}
}
Expand Down
14 changes: 13 additions & 1 deletion Sources/TestCommons/TestFixture/Geometria+Visualizable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extension PointNormal: VisualizableGeometricType2 where Vector: Vector2Type & Vi
}
}

extension Convex2Convex2Intersection: VisualizableGeometricType2 where Vector: Vector2Type & VisualizableGeometricType2, Vector.Scalar: Numeric & CustomStringConvertible {
extension ClosedShape2Intersection: VisualizableGeometricType2 where Vector: Vector2Type & VisualizableGeometricType2, Vector.Scalar: Numeric & CustomStringConvertible {
public func addVisualization2D(to printer: P5Printer, style: P5Printer.Style?, file: StaticString = #file, line: UInt = #line) {
printer.add(self, style: style, file: file, line: line)
}
Expand Down Expand Up @@ -101,3 +101,15 @@ extension Torus3: VisualizableGeometricType3 where Vector: VectorReal, Scalar: C
printer.add(self, style: style, file: file, line: line)
}
}

extension LinePolygon: VisualizableGeometricType2 where Vector: Vector2Real, Scalar: CustomStringConvertible {
public func addVisualization2D(to printer: P5Printer, style: P5Printer.Style?, file: StaticString = #file, line: UInt = #line) {
printer.add(self, style: style, file: file, line: line)
}
}

extension LinePolygon: VisualizableGeometricType3 where Vector: Vector3Real, Scalar: CustomStringConvertible {
public func addVisualization3D(to printer: P5Printer, style: P5Printer.Style?, file: StaticString = #file, line: UInt = #line) {
printer.add(self, style: style, file: file, line: line)
}
}
Loading

0 comments on commit 543a658

Please sign in to comment.