No flags found
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
408b1f3
... +0 ...
a243b69
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
43 | 43 | case cubic(to: Point, control1: Point, control2: Point) |
|
44 | 44 | case close |
|
45 | 45 | } |
|
46 | + | ||
47 | + | enum Direction { |
|
48 | + | case clockwise |
|
49 | + | case anticlockwise |
|
50 | + | } |
|
46 | 51 | ||
47 | 52 | func hash(into hasher: inout Hasher) { |
|
48 | 53 | hasher.combine(self.segments) |
125 | 130 | } |
|
126 | 131 | } |
|
127 | 132 | } |
|
133 | + | ||
134 | + | ||
135 | + | extension BidirectionalCollection where Element == LayerTree.Path.Segment, Index == Int { |
|
136 | + | ||
137 | + | // Determine direction by sign of calculated area |
|
138 | + | // https://www.101computing.net/the-shoelace-algorithm/ |
|
139 | + | // |
|
140 | + | var direction: LayerTree.Path.Direction { |
|
141 | + | var lhs: LayerTree.Float = 0 |
|
142 | + | var rhs: LayerTree.Float = 0 |
|
143 | + | for (current, next) in compactMap(\.location).paired(with: .nextWrappingToFirst) { |
|
144 | + | lhs += current.x * next.y |
|
145 | + | rhs += current.y * next.x |
|
146 | + | } |
|
147 | + | ||
148 | + | return (lhs - rhs) < 0 ? .anticlockwise : .clockwise |
|
149 | + | } |
|
150 | + | } |
|
151 | + | ||
152 | + | prefix func !(direction: LayerTree.Path.Direction) -> LayerTree.Path.Direction { |
|
153 | + | switch direction { |
|
154 | + | case .clockwise: |
|
155 | + | return .anticlockwise |
|
156 | + | case .anticlockwise: |
|
157 | + | return .clockwise |
|
158 | + | } |
|
159 | + | } |
1 | + | // |
|
2 | + | // PairedSequence.swift |
|
3 | + | // SwiftDraw |
|
4 | + | // |
|
5 | + | // Created by Simon Whitty on 6/8/22. |
|
6 | + | // Copyright 2022 Simon Whitty |
|
7 | + | // |
|
8 | + | // Distributed under the permissive zlib license |
|
9 | + | // Get the latest version from here: |
|
10 | + | // |
|
11 | + | // https://github.com/swhitty/SwiftDraw |
|
12 | + | // |
|
13 | + | // This software is provided 'as-is', without any express or implied |
|
14 | + | // warranty. In no event will the authors be held liable for any damages |
|
15 | + | // arising from the use of this software. |
|
16 | + | // |
|
17 | + | // Permission is granted to anyone to use this software for any purpose, |
|
18 | + | // including commercial applications, and to alter it and redistribute it |
|
19 | + | // freely, subject to the following restrictions: |
|
20 | + | // |
|
21 | + | // 1. The origin of this software must not be misrepresented; you must not |
|
22 | + | // claim that you wrote the original software. If you use this software |
|
23 | + | // in a product, an acknowledgment in the product documentation would be |
|
24 | + | // appreciated but is not required. |
|
25 | + | // |
|
26 | + | // 2. Altered source versions must be plainly marked as such, and must not be |
|
27 | + | // misrepresented as being the original software. |
|
28 | + | // |
|
29 | + | // 3. This notice may not be removed or altered from any source distribution. |
|
30 | + | // |
|
31 | + | ||
32 | + | extension Sequence { |
|
33 | + | ||
34 | + | // Iterate a sequence by including the next element each time. |
|
35 | + | // A---B---C---D |
|
36 | + | // |
|
37 | + | // nextSkippingLast: (A,B)--(B,C)--(C,D) |
|
38 | + | // nextWrappingToFirst: (A,B)--(B,C)--(C,D)--(D,A) |
|
39 | + | func paired(with options: PairedSequence<Self>.Options = .nextWrappingToFirst) -> PairedSequence<Self> { |
|
40 | + | PairedSequence(self, options: options) |
|
41 | + | } |
|
42 | + | } |
|
43 | + | ||
44 | + | struct PairedSequence<S: Sequence>: Sequence { |
|
45 | + | typealias Element = (S.Element, next: S.Element) |
|
46 | + | ||
47 | + | enum Options { |
|
48 | + | case nextSkippingLast |
|
49 | + | case nextWrappingToFirst |
|
50 | + | } |
|
51 | + | ||
52 | + | init(_ inner: S, options: Options) { |
|
53 | + | self.inner = inner |
|
54 | + | self.options = options |
|
55 | + | } |
|
56 | + | ||
57 | + | private let inner: S |
|
58 | + | private let options: Options |
|
59 | + | ||
60 | + | func makeIterator() -> Iterator { |
|
61 | + | return Iterator(inner.makeIterator(), options: options) |
|
62 | + | } |
|
63 | + | ||
64 | + | struct Iterator: IteratorProtocol { |
|
65 | + | private var inner: S.Iterator |
|
66 | + | private let options: Options |
|
67 | + | ||
68 | + | init(_ inner: S.Iterator, options: Options) { |
|
69 | + | self.inner = inner |
|
70 | + | self.options = options |
|
71 | + | } |
|
72 | + | ||
73 | + | mutating func next() -> (S.Element, next: S.Element)? { |
|
74 | + | guard !isComplete else { return nil } |
|
75 | + | ||
76 | + | guard let element = inner.next() else { |
|
77 | + | isComplete = true |
|
78 | + | return makeWrappedIfRequired() |
|
79 | + | } |
|
80 | + | ||
81 | + | if let previous = previous { |
|
82 | + | self.previous = element |
|
83 | + | return (previous, element) |
|
84 | + | } else { |
|
85 | + | first = element |
|
86 | + | if let another = inner.next() { |
|
87 | + | self.previous = another |
|
88 | + | return (element, another) |
|
89 | + | } else { |
|
90 | + | isComplete = true |
|
91 | + | return nil |
|
92 | + | } |
|
93 | + | } |
|
94 | + | } |
|
95 | + | ||
96 | + | private mutating func makeWrappedIfRequired() -> (S.Element, next: S.Element)? { |
|
97 | + | guard options == .nextWrappingToFirst, |
|
98 | + | let first = first, |
|
99 | + | let previous = previous else { |
|
100 | + | return nil |
|
101 | + | } |
|
102 | + | self.first = nil |
|
103 | + | self.previous = nil |
|
104 | + | return (previous, first) |
|
105 | + | } |
|
106 | + | ||
107 | + | private var isComplete: Bool = false |
|
108 | + | private var first: S.Element? |
|
109 | + | private var previous: S.Element? |
|
110 | + | } |
|
111 | + | } |
Learn more Showing 1 files with coverage changes found.
SwiftDraw/Utilities/PairedSequence.swift
Files | Coverage |
---|---|
SwiftDraw | 0.26% 76.30% |
Project Totals (60 files) | 76.30% |
a243b69
408b1f3