Skip to content

Commit

Permalink
shape edges merge improvement
Browse files Browse the repository at this point in the history
  • Loading branch information
NailxSharipov committed Jul 25, 2024
1 parent e16ee4b commit 69fd596
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 34 deletions.
4 changes: 3 additions & 1 deletion Sources/iOverlay/Core/Overlay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ public struct Overlay {

private func prepareSegments(fillRule: FillRule, solver: Solver) -> [Segment] {
var sortedEdges = edges.sorted(by: { $0.xSegment < $1.xSegment })


sortedEdges.mergeIfNeeded()

let isList = SplitSolver(solver: solver, range: sortedEdges.yRange()).split(edges: &sortedEdges)

var segments = sortedEdges.segments()
Expand Down
41 changes: 41 additions & 0 deletions Sources/iOverlay/Split/ShapeEdge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,44 @@ extension ShapeEdge: Comparable {
lhs.xSegment < rhs.xSegment
}
}

extension Array where Element == ShapeEdge {
mutating func mergeIfNeeded() {
guard self.count > 1 else {
return
}

var i = 1
while i < self.count {
if self[i - 1].xSegment == self[i].xSegment {
break
}
i += 1
}

guard i < self.count else {
return
}

var j = i - 1
var prev = self[j]

while i < self.count {
if prev.xSegment == self[i].xSegment {
prev.count = prev.count.add(self[i].count)
} else {
self[j] = prev
j += 1
prev = self[i]
}
i += 1
}

self[j] = prev
j += 1

if j < self.count {
self.removeLast(self.count - j)
}
}
}
27 changes: 1 addition & 26 deletions Sources/iOverlay/Split/SplitSolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,31 +88,6 @@ struct SplitSolver {

edges.sort(by: { $0.xSegment < $1.xSegment })

edges.merge()
}
}

private extension [ShapeEdge] {
mutating func merge() {
guard var prev = self.first else {
return
}
var isModified = false
var i = 1
while i < self.count {
if prev.xSegment == self[i].xSegment {
let c = self.remove(at: i).count
prev.count = prev.count.add(c)
isModified = true

continue
} else if isModified {
isModified = false
self[i - 1].count = prev.count
prev = self[i]
}

i += 1
}
edges.mergeIfNeeded()
}
}
27 changes: 20 additions & 7 deletions Tests/iOverlayTests/DinamycTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,39 @@ final class DinamycTests: XCTestCase {
var r = 0.004
while r < 1.0 {
for n in 5..<10 {
let subjPaths = self.randomPolygon(radius: r, n: n)
let subjPaths = self.randomPolygon(radius: r, angle: 0.0, n: n)

var overlay = Overlay(capacity: n)
overlay.add(path: subjPaths, type: .subject)

let graph = overlay.buildGraph(fillRule: .nonZero)
let result = graph.extractShapes(overlayRule: .subject)

XCTAssertTrue(!result.isEmpty)
_ = graph.extractShapes(overlayRule: .subject)
}
r += 0.001
}
}

func test_31() throws {
let n = 100
let subjPath = self.randomPolygon(radius: 1000.0, angle: 0.0, n: n)
let clipPath = self.randomPolygon(radius: 1000.0, angle: 0.5, n: n)

var overlay = Overlay(capacity: 2 * n)
overlay.add(path: subjPath, type: .subject)
overlay.add(path: clipPath, type: .clip)

let graph = overlay.buildGraph(fillRule: .nonZero, solver: .list)
let result = graph.extractShapes(overlayRule: .union)

XCTAssertTrue(!result.isEmpty)
}


func randomPolygon(radius: Double, n: Int) -> Path {
func randomPolygon(radius: Double, angle: Double, n: Int) -> Path {
var result = Path()
result.reserveCapacity(n)
let da = Double.pi * 0.7
var a = 0.0
let da = 0.005
var a = angle
let r = radius * 1024
for _ in 0..<n {
let s = sin(a)
Expand Down

0 comments on commit 69fd596

Please sign in to comment.