diff --git a/.DS_Store b/.DS_Store new file mode 100755 index 0000000..13424e0 Binary files /dev/null and b/.DS_Store differ diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml new file mode 100644 index 0000000..f0b2404 --- /dev/null +++ b/.github/workflows/swift.yml @@ -0,0 +1,18 @@ +name: Swift + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Build + run: swift build -v + diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata old mode 100644 new mode 100755 diff --git a/Documentation/BeachlineSegment.md b/Documentation/BeachlineSegment.md new file mode 100755 index 0000000..4492a20 --- /dev/null +++ b/Documentation/BeachlineSegment.md @@ -0,0 +1,25 @@ +# BeachlineSegment + +``` swift +public struct BeachlineSegment +``` + +## Properties + +### `parabola` + +``` swift +let parabola: Parabola +``` + +### `lBoundX` + +``` swift +let lBoundX: Double +``` + +### `rBoundX` + +``` swift +let rBoundX: Double +``` diff --git a/Documentation/Cell.md b/Documentation/Cell.md new file mode 100755 index 0000000..75318af --- /dev/null +++ b/Documentation/Cell.md @@ -0,0 +1,55 @@ +# Cell + +Stores pointer to: +• `outerComponent` linked list (looped when diagram is built) +• `site` - pointer to the site + +``` swift +public class Cell +``` + +## Initializers + +### `init(site:)` + +``` swift +public init(site: Site) +``` + +## Properties + +### `satellite` + +``` swift +var satellite: Any? +``` + +### `outerComponent` + +``` swift +var outerComponent: HalfEdge? +``` + +### `site` + +``` swift +var site: Site +``` + +## Methods + +### `hullVerticesCCW()` + +Returns hell vertices of the cell + +``` swift +func hullVerticesCCW() -> [Vertex] +``` + +### `neighbours()` + +Returns all the neighbours of specific cell + +``` swift +func neighbours() -> [Cell] +``` diff --git a/Documentation/Circle.md b/Documentation/Circle.md new file mode 100755 index 0000000..f13a5e8 --- /dev/null +++ b/Documentation/Circle.md @@ -0,0 +1,49 @@ +# Circle + +``` swift +public struct Circle +``` + +## Initializers + +### `init?(p1:p2:p3:)` + +Defines circle by three points +See: https://www.xarg.org/2018/02/create-a-circle-out-of-three-points/ + +``` swift +public init?(p1: Point, p2: Point, p3: Point) +``` + +### `init(center:radius:)` + +Constructor. Defines a Circle by it's center and radius + +``` swift +public init(center: Point, radius: Double) +``` + +#### Parameters + + - center: - center: Circle origin (center) + - radius: - radius: Circle radius + +## Properties + +### `center` + +``` swift +let center: Point +``` + +### `radius` + +``` swift +let radius: Double +``` + +### `bottomPoint` + +``` swift +var bottomPoint: Point +``` diff --git a/Documentation/Clipper.md b/Documentation/Clipper.md new file mode 100755 index 0000000..e2852db --- /dev/null +++ b/Documentation/Clipper.md @@ -0,0 +1,31 @@ +# Clipper + +``` swift +public struct Clipper +``` + +## Properties + +### `left` + +``` swift +let left: Double +``` + +### `right` + +``` swift +let right: Double +``` + +### `top` + +``` swift +let top: Double +``` + +### `bottom` + +``` swift +let bottom: Double +``` diff --git a/Documentation/Diagram.md b/Documentation/Diagram.md new file mode 100755 index 0000000..c6cc1b6 --- /dev/null +++ b/Documentation/Diagram.md @@ -0,0 +1,47 @@ +# Diagram + +``` swift +public class Diagram +``` + +## Initializers + +### `init()` + +``` swift +public init() +``` + +## Properties + +### `cells` + +``` swift +var cells +``` + +### `vertices` + +``` swift +var vertices +``` + +## Methods + +### `createCell(_:)` + +``` swift +func createCell(_ arc: Arc) +``` + +### `createHalfEdge(_:)` + +``` swift +func createHalfEdge(_ cell: Cell) -> HalfEdge +``` + +### `clear()` + +``` swift +public func clear() +``` diff --git a/Documentation/FortuneSweep.md b/Documentation/FortuneSweep.md new file mode 100755 index 0000000..9f753eb --- /dev/null +++ b/Documentation/FortuneSweep.md @@ -0,0 +1,301 @@ +# FortuneSweep + +``` swift +public class FortuneSweep +``` + +## Initializers + +### `init(logger:watcher:)` + +Initialises new FortuneSweep instance +NB: `logger` and especially `watcher` will affect performance\! +Use them only for debug purposes\! + +``` swift +public init(logger: FortuneSweepLogging? = nil, watcher: FortuneSweepProgressWatching? = nil) +``` + +#### Parameters + + - logger: - logger: Optional. Calls `log` function when importand events happen + - watcher: - watcher: Optional. **Affects performance\!** Tracks diagram building process. May be used for visualisation as it includes useful scaffolding. + +## Properties + +### `eventQueue` + +Service Data Structures + +``` swift +var eventQueue: PriorityQueue! +``` + +### `beachline` + +``` swift +var beachline: Beachline! +``` + +### `sweepLineY` + +``` swift +var sweepLineY: Double +``` + +### `firstSiteY` + +``` swift +var firstSiteY: Double? +``` + +### `container` + +``` swift +var container: Rectangle! +``` + +### `clipper` + +``` swift +var clipper: Rectangle! +``` + +### `logger` + +Debug Data structures + +``` swift +var logger: FortuneSweepLogging? +``` + +### `watcher` + +``` swift +var watcher: FortuneSweepProgressWatching? +``` + +### `currentStep` + +``` swift +var currentStep: Int +``` + +### `isTerminated` + +``` swift +var isTerminated: Bool! +``` + +### `diagram` + +Result Data Structure + +``` swift +var diagram: Diagram! +``` + +## Methods + +### `compute(sites:diagram:clippingRect:maxStepsCount:)` + +``` swift +public func compute(sites: Set, diagram: inout Diagram, clippingRect: Rectangle, maxStepsCount: Int = -1) -> Bool +``` + +### `debug_step()` + +Runs one step of an algorithm + +``` swift +func debug_step() -> Bool +``` + +### `step()` + +Performs one step of the algorithm + +``` swift +private func step() +``` + +1. Pop an event from the event queue +2. Check the event type and process the event appropriately + +### `processSiteEvent(_:)` + +Processes **Site event** and performs all the necessary actions + +``` swift +private func processSiteEvent(_ event: Event) +``` + +#### Parameters + + - event: - event: **Site Event** to process + +### `createVertex(_:removedArc:)` + +When Circle event took place we must create a **Vertex** record in the Diagram. + +``` swift +private func createVertex(_ vertex: Vertex, removedArc: Arc) +``` + +#### Parameters + + - vertex: - vertex: Vertex coordinate (e.g. Circle event center) + - removedArc: - removedArc: The arc that will be removed from the **Beachline** after the Circle event + +### `processCircleEvent(_:)` + +Processes circle event and performs all the necessary actions + +``` swift +private func processCircleEvent(_ event: Event) +``` + +#### Parameters + + - event: - event: **Circle Event** + +### `createCircleEvent(_:)` + +Creates circle event for the coresponding **Arc** in the **Beachline** +Adds **Circle Event** into **Priority Queue** +Sets ponters between **Circle Event** and **Arc** + +``` swift +private func createCircleEvent(_ arc: Arc) +``` + +#### Parameters + + - arc: - arc: **Beachline** arc to add event + - circle: - circle: Circle represented by three points + +### `removeCircleEvent(_:)` + +Removes circle event from the **Priority Queue** and removes event from the **Arc** + +``` swift +private func removeCircleEvent(_ arc: Arc?) +``` + +#### Parameters + + - arc: - arc: **Arc** to strip from **Circle Event** + +### `terminate()` + +Algorithm termination + +``` swift +private func terminate() +``` + +1. Bound incomplete arcs to Maximum rectangle +2. Complete incomplete cells +3. Clip cells to clipping rectangle + +### `completeIncompleteCell(_:)` + +Some of the cells will not be completed (Are not looped linked list of half-edges) + +``` swift +private func completeIncompleteCell(_ cell: Cell) +``` + +#### Parameters + + - cell: - cell: cell to complete + +### `boundIncompleteArc(_:)` + +Bounds incomplete arcs to the maximum rectangle +Maximum rectangle is a `Rectangle` containing ALL diagram vertexes. It is expanded as + +``` swift +private func boundIncompleteArc(_ arc: Arc) +``` + +#### Parameters + + - arc: - arc: `Arc` from the beachline + +### `clipCell(_:clippingRect:)` + +Clips cell agains clipping `Rectangle`. There are few limitations: + +``` swift +private func clipCell(_ cell: Cell, clippingRect: Rectangle) +``` + +#### Parameters + + - cell: - cell: cell to clip + - clippingRect: - clippingRect: clipping rect + +### `halfEdgesChain(cell:clippingRect:start:end:)` + +Returns linked list of half-edges belonging to the clipping rect (maximum 4) represented as a pair + +``` swift +private func halfEdgesChain(cell: Cell, clippingRect: Rectangle, start: Site, end: Site) -> (HalfEdge, HalfEdge)? +``` + +#### Parameters + + - cell: - cell: half-edges owning `Cell` + - clippingRect: - clippingRect: Clipping rectangle + - start: - start: head origin + - end: - end: tail destination + +### `getBoxIntersection(_:_:_:)` + +Finds the intersection point for the bisector of the Line Segment defined by two points and Rectangle + +``` swift +private func getBoxIntersection(_ p1: Site, _ p2: Site, _ rectangle: Rectangle) -> Site +``` + +#### Parameters + + - p1: - p1: Point + - p2: - p2: Point + - rectangle: - rectangle: Rectangle + +### `makeTwins(_:_:)` + +When the Cell has common edge with another cell, thir corresponding **HalfEdges** are twins. +It means they have a pointer to each other and `a.origin == b.destination` and vice versa +This helper sets appropriate pointers between half edges + +``` swift +private func makeTwins(_ a: HalfEdge?, _ b: HalfEdge?) +``` + +### `connect(prev:next:)` + +Each cell is represented as **Doubly connected** linked list of **HalfEdges** +This helper connects two half edges appropriately + +``` swift +private func connect(prev: HalfEdge?, next: HalfEdge?) +``` + +### `checkCircleEvent(left:mid:right:)` + +Receives three arcs as an input and returns a circle, if the arc's points are not collinear and converging. +Convergence means that at some point `mid` arc will be removed (Circle event will take place) +Keep in mind that the fact that three points define a circle is not enough for circle event to take place + +``` swift +private func checkCircleEvent(left: Arc?, mid: Arc, right: Arc?) -> Circle? +``` + +#### Parameters + + - left: - left: left arc + - mid: - mid: middle arc + - right: - right: right arc diff --git a/Documentation/FortuneSweepLogging.md b/Documentation/FortuneSweepLogging.md new file mode 100755 index 0000000..db30784 --- /dev/null +++ b/Documentation/FortuneSweepLogging.md @@ -0,0 +1,20 @@ +# FortuneSweepLogging + +``` swift +public protocol FortuneSweepLogging +``` + +## Requirements + +## log(\_:level:) + +Depending on implemntation prints/saves log messages + +``` swift +func log(_ message: String, level: FortuneSweppLogLevel) +``` + +### Parameters + + - text: - text: Log message + - level: - level: Log level diff --git a/Documentation/FortuneSweepProgressWatching.md b/Documentation/FortuneSweepProgressWatching.md new file mode 100755 index 0000000..ad7c323 --- /dev/null +++ b/Documentation/FortuneSweepProgressWatching.md @@ -0,0 +1,180 @@ +# FortuneSweepProgressWatching + +``` swift +public protocol FortuneSweepProgressWatching: class +``` + +## Inheritance + +`class` + +## Requirements + +## step + +Depicts current step of an algorithm + +``` swift +var step: Int +``` + +## prepare(sites:clipper:) + +Called when algorithm is ready to work + +``` swift +func prepare(sites: Set, clipper: Rectangle) +``` + +### Parameters + + - sites: - sites: Same as Fortunes Algorithm input + - clipper: - clipper: Clipping rectangle + +## updateSweepline(y:) + +Called when sweepline changes position + +``` swift +func updateSweepline(y: Double) +``` + +### Parameters + + - y: - y: New sweepline Y position + +## siteEvent(site:) + +Called when Site Event occured + +``` swift +func siteEvent(site: Site) +``` + +### Parameters + + - site: - site: Visited site + +## circleEvent(point:) + +Called when Circle Event occured + +``` swift +func circleEvent(point: Point) +``` + +### Parameters + + - site: - site: Visited site + +## updateContainer(rectangle:) + +Called when bounding rectangle is changed + +``` swift +func updateContainer(rectangle: Rectangle) +``` + +### Parameters + + - rectangle: - rectangle: New Bounding rectangle + +## updateCurentBreakpoint(point:) + +Called when new breakpoint occured + +``` swift +func updateCurentBreakpoint(point: Point?) +``` + +### Parameters + + - point: - point: Breakpoint + +## updateBeachline(arcs:) + +Called when beachline is updated + +``` swift +func updateBeachline(arcs: [BeachlineSegment]) +``` + +### Parameters + + - arcs: - arcs: Arcs, currently present in the Beachline + +## addUpcomingCircleEvent(circle:) + +Called when upcoming circle event is added to the Event Queue + +``` swift +func addUpcomingCircleEvent(circle: Circle) +``` + +### Parameters + + - circle: - circle: Circle event circle + +## removeFalseAlarmCircleEvent(circle:) + +Called when Circle event is removed from Event Queue + +``` swift +func removeFalseAlarmCircleEvent(circle: Circle) +``` + +### Parameters + + - circle: - circle: Circle event circle + +## createVertex(vertex:) + +Called when new Vertex is created + +``` swift +func createVertex(vertex: Vertex) +``` + +### Parameters + + - vertex: - vertex: Vertex + +## createCell(cell:) + +Called when new Cell is added to the diagram + +``` swift +func createCell(cell: Cell) +``` + +### Parameters + + - cell: - cell: Cell + +## addHalfEdges(hes:) + +Called when HalfEdges are added to the diagram + +``` swift +func addHalfEdges(hes: [HalfEdge]) +``` + +### Parameters + + - hes: - hes: List of recently added HalfEdges + +## boundingDone() + +Called when Cells bounding is done + +``` swift +func boundingDone() +``` + +## workDone() + +Called when algorithm finished working + +``` swift +func workDone() +``` diff --git a/Documentation/FortuneSweppLogLevel.md b/Documentation/FortuneSweppLogLevel.md new file mode 100755 index 0000000..28c46b9 --- /dev/null +++ b/Documentation/FortuneSweppLogLevel.md @@ -0,0 +1,33 @@ +# FortuneSweppLogLevel + +\<\#Description\#\> + +``` swift +public enum FortuneSweppLogLevel +``` + +## Enumeration Cases + +### `info` + +``` swift +case info +``` + +### `warning` + +``` swift +case warning +``` + +### `error` + +``` swift +case error +``` + +### `critical` + +``` swift +case critical +``` diff --git a/Documentation/HalfEdge.md b/Documentation/HalfEdge.md new file mode 100755 index 0000000..bf2da28 --- /dev/null +++ b/Documentation/HalfEdge.md @@ -0,0 +1,64 @@ +# HalfEdge + +The half‐edge record of a half‐edge e stores pointer to: +• Origin(e) +• Twin of e, e.twin or twin(e) +• The face to its left (IncidentFace(e)) +• Next(e): next half‐edge on the boundary of IncidentFace(e) +• Previous(e): previous half‐edge + +``` swift +public class HalfEdge +``` + +## Properties + +### `satellite` + +``` swift +var satellite: Any? +``` + +### `origin` + +``` swift +var origin: Vertex? +``` + +### `destination` + +``` swift +var destination: Vertex? +``` + +### `twin` + +``` swift +var twin: HalfEdge? +``` + +### `incidentFace` + +``` swift +var incidentFace: Cell? +``` + +### `prev` + +``` swift +var prev: HalfEdge? +``` + +### `next` + +``` swift +var next: HalfEdge? +``` + +## Methods + +### `toSegment()` + +``` swift +func toSegment() -> LineSegment? +``` diff --git a/Documentation/Home.md b/Documentation/Home.md new file mode 100755 index 0000000..a38350a --- /dev/null +++ b/Documentation/Home.md @@ -0,0 +1,52 @@ +# Types + + - [PriorityQueue](/Documentation/PriorityQueue.md): + A PriorityQueue takes objects to be pushed of any type that implements Comparable. + It will pop the objects in the order that they would be sorted. A pop() or a push() + can be accomplished in O(lg n) time. It can be specified whether the objects should + be popped in ascending or descending order (Max Priority Queue or Min Priority Queue) + at the time of initialization. + - [Diagram](/Documentation/Diagram.md) + - [Cell](/Documentation/Cell.md): + Stores pointer to: + • `outerComponent` linked list (looped when diagram is built) + • `site` - pointer to the site + - [HalfEdge](/Documentation/HalfEdge.md): + The half‐edge record of a half‐edge e stores pointer to: + • Origin(e) + • Twin of e, e.twin or twin(e) + • The face to its left (IncidentFace(e)) + • Next(e): next half‐edge on the boundary of IncidentFace(e) + • Previous(e): previous half‐edge + - [FortuneSweep](/Documentation/FortuneSweep.md) + - [BeachlineSegment](/Documentation/BeachlineSegment.md) + - [FortuneSweppLogLevel](/Documentation/FortuneSweppLogLevel.md): + \<\#Description\#\> + - [Circle](/Documentation/Circle.md) + - [Clipper](/Documentation/Clipper.md) + - [LineSegment](/Documentation/LineSegment.md) + - [Parabola](/Documentation/Parabola.md) + - [Rectangle](/Documentation/Rectangle.md) + - [Rectangle.Edge](/Documentation/Rectangle_Edge.md) + - [Site](/Documentation/Site.md): + Represent the Point in 2D Cartesian coordinate system + - [Size](/Documentation/Size.md): + Represents the size of Rectangular object + - [Vector2D](/Documentation/Vector2D.md) + +# Protocols + + - [FortuneSweepLogging](/Documentation/FortuneSweepLogging.md) + - [FortuneSweepProgressWatching](/Documentation/FortuneSweepProgressWatching.md) + +# Global Typealiases + + - [Vertex](/Documentation/Vertex.md): + The vertex record of a vertex v stores the coordinates of v. + It also stores a pointer IncidentEdge(v) to an arbitrary half‐edge that has v as its origin + - [Point](/Documentation/Point.md) + - [LiangBarskyResult](/Documentation/LiangBarskyResult.md) + +# Global Functions + + - [lb\_clip(\_:clipper:)](/Documentation/lb_clip\(_:clipper:\).md) diff --git a/Documentation/LiangBarskyResult.md b/Documentation/LiangBarskyResult.md new file mode 100755 index 0000000..b1aeffd --- /dev/null +++ b/Documentation/LiangBarskyResult.md @@ -0,0 +1,5 @@ +# LiangBarskyResult + +``` swift +public typealias LiangBarskyResult = (isOriginClipped: Bool, isDestinationClipped: Bool, resultSegment: LineSegment?) +``` diff --git a/Documentation/LineSegment.md b/Documentation/LineSegment.md new file mode 100755 index 0000000..b23aef0 --- /dev/null +++ b/Documentation/LineSegment.md @@ -0,0 +1,41 @@ +# LineSegment + +``` swift +public struct LineSegment +``` + +## Initializers + +### `init(a:b:)` + +``` swift +public init(a: Site, b: Site) +``` + +## Properties + +### `a` + +``` swift +var a: Site +``` + +### `b` + +``` swift +var b: Site +``` + +## Methods + +### `containsPoint(_:)` + +``` swift +func containsPoint(_ point: Site) -> Bool +``` + +### `length()` + +``` swift +func length() -> Double +``` diff --git a/Documentation/Parabola.md b/Documentation/Parabola.md new file mode 100755 index 0000000..11ed015 --- /dev/null +++ b/Documentation/Parabola.md @@ -0,0 +1,81 @@ +# Parabola + +``` swift +public struct Parabola +``` + +## Initializers + +### `init(focus:directrixY:)` + +Constructor that defines parabola by the focus and the directrix that is **Parallel** to *X-axis*\! + +``` swift +public init(focus: Site, directrixY: Double) +``` + +#### Parameters + + - focus: - focus: Parabola focus + - directrixY: - directrixY: Directix *Y* + +## Properties + +### `focus` + +``` swift +var focus: Site +``` + +### `directrixY` + +``` swift +var directrixY: Double +``` + +### `standardForm` + +Converts parabola to standart form (ax^2 + by \* c) + +``` swift +var standardForm: (a: Double, b: Double, c: Double) +``` + +## Methods + +### `resolve(x:)` + +Resolves parabola equation against given *X* + +``` swift +public func resolve(x: Double) -> Double +``` + +#### Parameters + + - x: - x: given x + +### `toQuadBezier(minX:maxX:)` + +Quadrativ Bezier representation of the Parabola clipped by *X* + +``` swift +public func toQuadBezier(minX: Double, maxX: Double) -> (start: Site, cp: Site, end: Site) +``` + +#### Parameters + + - minX: - minX: Min *X* clippling point + - maxX: - maxX: Max *X* clippling point + +### `intersectionX(_:)` + +*X* coordinate of the intersection with other Parabola (if present) + +``` swift +public func intersectionX(_ parabola: Parabola) -> Double? +``` + +#### Parameters + + - parabola: - parabola: other parabola diff --git a/Documentation/Point.md b/Documentation/Point.md new file mode 100755 index 0000000..af90b79 --- /dev/null +++ b/Documentation/Point.md @@ -0,0 +1,5 @@ +# Point + +``` swift +public typealias Point = Site +``` diff --git a/Documentation/PriorityQueue.md b/Documentation/PriorityQueue.md new file mode 100755 index 0000000..2c51b5e --- /dev/null +++ b/Documentation/PriorityQueue.md @@ -0,0 +1,212 @@ +# PriorityQueue + +A PriorityQueue takes objects to be pushed of any type that implements Comparable. +It will pop the objects in the order that they would be sorted. A pop() or a push() +can be accomplished in O(lg n) time. It can be specified whether the objects should +be popped in ascending or descending order (Max Priority Queue or Min Priority Queue) +at the time of initialization. + +``` swift +public struct PriorityQueue +``` + +## Inheritance + +`Collection`, `CustomDebugStringConvertible`, `CustomStringConvertible`, `IteratorProtocol`, `Sequence` + +## Nested Type Aliases + +### `Element` + +``` swift +public typealias Element = T +``` + +### `Iterator` + +``` swift +public typealias Iterator = PriorityQueue +``` + +### `Index` + +``` swift +public typealias Index = Int +``` + +## Initializers + +### `init(ascending:startingValues:)` + +``` swift +public init(ascending: Bool = false, startingValues: [T] = []) +``` + +### `init(order:startingValues:)` + +Creates a new PriorityQueue with the given ordering. + +``` swift +public init(order: @escaping (T, T) -> Bool, startingValues: [T] = []) +``` + +#### Parameters + + - order: - order: A function that specifies whether its first argument should come after the second argument in the PriorityQueue. + - startingValues: - startingValues: An array of elements to initialize the PriorityQueue with. + +## Properties + +### `heap` + +``` swift +var heap +``` + +### `ordered` + +``` swift +let ordered: (T, T) -> Bool +``` + +### `count` + +How many elements the Priority Queue stores + +``` swift +var count: Int +``` + +### `isEmpty` + +true if and only if the Priority Queue is empty + +``` swift +var isEmpty: Bool +``` + +### `startIndex` + +``` swift +var startIndex: Int +``` + +### `endIndex` + +``` swift +var endIndex: Int +``` + +### `description` + +``` swift +var description: String +``` + +### `debugDescription` + +``` swift +var debugDescription: String +``` + +## Methods + +### `push(_:)` + +Add a new element onto the Priority Queue. O(lg n) + +``` swift +public mutating func push(_ element: T) +``` + +#### Parameters + + - element: - element: The element to be inserted into the Priority Queue. + +### `pop()` + +Remove and return the element with the highest priority (or lowest if ascending). O(lg n) + +``` swift +public mutating func pop() -> T? +``` + +#### Returns + +The element with the highest priority in the Priority Queue, or nil if the PriorityQueue is empty. + +### `remove(_:)` + +Removes the first occurence of a particular item. Finds it by value comparison using ==. O(n) +Silently exits if no occurrence found. + +``` swift +public mutating func remove(_ item: T) +``` + +#### Parameters + + - item: - item: The item to remove the first occurrence of. + +### `removeAll(_:)` + +Removes all occurences of a particular item. Finds it by value comparison using ==. O(n) +Silently exits if no occurrence found. + +``` swift +public mutating func removeAll(_ item: T) +``` + +#### Parameters + + - item: - item: The item to remove. + +### `peek()` + +Get a look at the current highest priority item, without removing it. O(1) + +``` swift +public func peek() -> T? +``` + +#### Returns + +The element with the highest priority in the PriorityQueue, or nil if the PriorityQueue is empty. + +### `clear()` + +Eliminate all of the elements from the Priority Queue. + +``` swift +public mutating func clear() +``` + +### `sink(_:)` + +``` swift +private mutating func sink(_ index: Int) +``` + +### `swim(_:)` + +``` swift +private mutating func swim(_ index: Int) +``` + +### `next()` + +``` swift +mutating public func next() -> Element? +``` + +### `makeIterator()` + +``` swift +public func makeIterator() -> Iterator +``` + +### `index(after:)` + +``` swift +public func index(after i: PriorityQueue.Index) -> PriorityQueue.Index +``` diff --git a/Documentation/Rectangle.md b/Documentation/Rectangle.md new file mode 100755 index 0000000..02cd897 --- /dev/null +++ b/Documentation/Rectangle.md @@ -0,0 +1,143 @@ +# Rectangle + +``` swift +public struct Rectangle +``` + +## Initializers + +### `init(origin:size:)` + +``` swift +public init(origin: Site, size: Size) +``` + +## Properties + +### `x` + +``` swift +var x: Double +``` + +### `y` + +``` swift +var y: Double +``` + +### `width` + +``` swift +var width: Double +``` + +### `height` + +``` swift +var height: Double +``` + +### `tl` + +``` swift +var tl: Site +``` + +### `bl` + +``` swift +var bl: Site +``` + +### `tr` + +``` swift +var tr: Site +``` + +### `br` + +``` swift +var br: Site +``` + +### `origin` + +``` swift +var origin: Site +``` + +### `size` + +``` swift +var size: Size +``` + +## Methods + +### `expandToContainPoint(_:padding:)` + +``` swift +public mutating func expandToContainPoint(_ p: Site, padding: Double = 20.0) +``` + +### `getLine(_:)` + +``` swift +public func getLine(_ edge: Edge) -> LineSegment +``` + +### `getEdges()` + +``` swift +public func getEdges() -> [LineSegment] +``` + +### `rect(from:with:)` + +``` swift +public static func rect(from sourceRect: Rectangle, with padding: Double) -> Rectangle +``` + +### `contains(_:)` + +``` swift +func contains(_ point: Site?) -> Bool +``` + +### `intersection(origin:direction:)` + +``` swift +func intersection(origin: Site, direction: Vector2D) -> (point: Site, edge: Rectangle.Edge) +``` + +### `getNextCCW(_:)` + +``` swift +private func getNextCCW(_ edge: Edge) -> (edge: Edge, corner: Site) +``` + +### `sideForPoint(p:)` + +``` swift +func sideForPoint(p: Site) -> Edge? +``` + +### `ccwTraverse(startEdge:endEdge:)` + +``` swift +func ccwTraverse(startEdge: Edge, endEdge: Edge) -> [Site] +``` + +### `getRectPolylineForCCW(_:end:)` + +``` swift +func getRectPolylineForCCW(_ start: Site, end: Site) -> [Site] +``` + +### `toClipper()` + +``` swift +public func toClipper() -> Clipper +``` diff --git a/Documentation/Rectangle_Edge.md b/Documentation/Rectangle_Edge.md new file mode 100755 index 0000000..5bb3bf7 --- /dev/null +++ b/Documentation/Rectangle_Edge.md @@ -0,0 +1,35 @@ +# Rectangle.Edge + +``` swift +public enum Edge +``` + +## Inheritance + +`CaseIterable` + +## Enumeration Cases + +### `top` + +``` swift +case top +``` + +### `right` + +``` swift +case right +``` + +### `bottom` + +``` swift +case bottom +``` + +### `left` + +``` swift +case left +``` diff --git a/Documentation/Site.md b/Documentation/Site.md new file mode 100755 index 0000000..b09b350 --- /dev/null +++ b/Documentation/Site.md @@ -0,0 +1,71 @@ +# Site + +Represent the Point in 2D Cartesian coordinate system + +``` swift +public struct Site +``` + +## Inheritance + +`CustomStringConvertible`, `Hashable` + +## Initializers + +### `init(x:y:)` + +``` swift +public init(x: Double, y: Double) +``` + +## Properties + +### `vector` + +``` swift +var vector: Vector2D +``` + +### `satellite` + +``` swift +var satellite: Any? +``` + +### `x` + +``` swift +var x: Double +``` + +### `y` + +``` swift +var y: Double +``` + +### `description` + +``` swift +var description: String +``` + +## Methods + +### `distance(to:)` + +``` swift +func distance(to point: Site) -> Double +``` + +### `==(lhs:rhs:)` + +``` swift +public static func ==(lhs: Site, rhs: Site) -> Bool +``` + +### `hash(into:)` + +``` swift +public func hash(into hasher: inout Hasher) +``` diff --git a/Documentation/Size.md b/Documentation/Size.md new file mode 100755 index 0000000..62c115a --- /dev/null +++ b/Documentation/Size.md @@ -0,0 +1,29 @@ +# Size + +Represents the size of Rectangular object + +``` swift +public struct Size +``` + +## Initializers + +### `init(width:height:)` + +``` swift +public init(width: Double, height: Double) +``` + +## Properties + +### `width` + +``` swift +var width: Double +``` + +### `height` + +``` swift +var height: Double +``` diff --git a/Documentation/Vector2D.md b/Documentation/Vector2D.md new file mode 100755 index 0000000..d9757ef --- /dev/null +++ b/Documentation/Vector2D.md @@ -0,0 +1,71 @@ +# Vector2D + +``` swift +public struct Vector2D +``` + +## Initializers + +### `init(dx:dy:)` + +``` swift +public init(dx: Double, dy: Double) +``` + +## Properties + +### `normal` + +``` swift +var normal: Vector2D +``` + +### `point` + +``` swift +var point: Site +``` + +### `dx` + +``` swift +var dx +``` + +### `dy` + +``` swift +var dy +``` + +### `magnitude` + +``` swift +var magnitude: Double +``` + +## Methods + +### `+(left:right:)` + +``` swift +public static func +(left: Vector2D, right: Vector2D) -> Vector2D +``` + +### `-(left:right:)` + +``` swift +public static func -(left: Vector2D, right: Vector2D) -> Vector2D +``` + +### `*(left:right:)` + +``` swift +static func *(left: Double, right: Vector2D) -> Vector2D +``` + +### `*(left:right:)` + +``` swift +static func *(left: Vector2D, right: Double) -> Vector2D +``` diff --git a/Documentation/Vertex.md b/Documentation/Vertex.md new file mode 100755 index 0000000..725d751 --- /dev/null +++ b/Documentation/Vertex.md @@ -0,0 +1,8 @@ +# Vertex + +The vertex record of a vertex v stores the coordinates of v. +It also stores a pointer IncidentEdge(v) to an arbitrary half‐edge that has v as its origin + +``` swift +public typealias Vertex = Site +``` diff --git a/Documentation/_Footer.md b/Documentation/_Footer.md new file mode 100755 index 0000000..c466ddc --- /dev/null +++ b/Documentation/_Footer.md @@ -0,0 +1 @@ +Generated at 2020-06-02T09:31:39+0300 using [swift-doc](https://github.com/SwiftDocOrg/swift-doc) 1.0.0-beta.3. diff --git a/Documentation/_Sidebar.md b/Documentation/_Sidebar.md new file mode 100755 index 0000000..38d2f8d --- /dev/null +++ b/Documentation/_Sidebar.md @@ -0,0 +1,45 @@ +
+Types + + - [BeachlineSegment](/BeachlineSegment) + - [Cell](/Cell) + - [Circle](/Circle) + - [Clipper](/Clipper) + - [Diagram](/Diagram) + - [FortuneSweep](/FortuneSweep) + - [FortuneSweppLogLevel](/FortuneSweppLogLevel) + - [HalfEdge](/HalfEdge) + - [LineSegment](/LineSegment) + - [Parabola](/Parabola) + - [PriorityQueue](/PriorityQueue) + - [Rectangle](/Rectangle) + - [Rectangle.Edge](/Rectangle.Edge) + - [Site](/Site) + - [Size](/Size) + - [Vector2D](/Vector2D) + +
+ +
+Protocols + + - [FortuneSweepLogging](/FortuneSweepLogging) + - [FortuneSweepProgressWatching](/FortuneSweepProgressWatching) + +
+ +
+Global Typealiases + + - [LiangBarskyResult](/LiangBarskyResult) + - [Point](/Point) + - [Vertex](/Vertex) + +
+ +
+Global Functions + + - [lb\_clip(\_:clipper:)](/lb_clip\(_:clipper:\)) + +
diff --git a/Documentation/lb_clip(_:clipper:).md b/Documentation/lb_clip(_:clipper:).md new file mode 100755 index 0000000..fd131c4 --- /dev/null +++ b/Documentation/lb_clip(_:clipper:).md @@ -0,0 +1,5 @@ +# lb\_clip(\_:clipper:) + +``` swift +public func lb_clip(_ line: LineSegment, clipper: Clipper) -> LiangBarskyResult +``` diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/Package.swift b/Package.swift old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 62f658d..e96f136 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ # FortunesAlgorithm +![Swift](https://github.com/fewlinesofcode/FortunesAlgorithm/workflows/Swift/badge.svg) + `FortunesAlgorithm` is a Swift package for building Voronoi diagrams using Steven Fortune's algorithm. Algorithm guarantees `O(n log n)` worst-case running time and uses `O(n)` space. +You can learn more about the project using [Documentation](https://github.com/fewlinesofcode/FortunesAlgorithm/blob/master/Documentation/Home.md) + # Installing `FortunesAlgorithm` can be installed as any other Swift package. Add the following to the `dependencies` section of your `Package.swift`: diff --git a/Sources/FortunesAlgorithm/Beachline.swift b/Sources/FortunesAlgorithm/Beachline.swift index 4dfb484..694575b 100755 --- a/Sources/FortunesAlgorithm/Beachline.swift +++ b/Sources/FortunesAlgorithm/Beachline.swift @@ -1,26 +1,25 @@ -/* -MIT License +// MIT License +// +// Copyright (c) 2020 Oleksandr Glagoliev +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ final class Arc { var isBlack: Bool = true @@ -299,31 +298,7 @@ extension Beachline { func updateSweeplineY(_ y: Double) { sweeplineY = y } - -// private func arcAbovePoint(_ p: Point) -> Arc { -// var x: Arc = root! -// var found = false -// while !found { -// assert(x.point != nil) -// let (l, r) = x.bounds(sweeplineY) -// if p.x < l { -// x = x.left! -// } else if p.x > r { -// x = x.right! -// } -// else if abs(p.x - l) < eps { -// x = x.prev! -// found = true -// } else if abs(p.x - r) < eps { -// found = true -// } -// else { -// found = true -// } -// } -// return x -// } - + func addAsLeftChild(_ x: Arc, _ y: Arc) { y.left = x x.parent = y diff --git a/Sources/FortunesAlgorithm/Debug.swift b/Sources/FortunesAlgorithm/Debug.swift deleted file mode 100755 index 39c6491..0000000 --- a/Sources/FortunesAlgorithm/Debug.swift +++ /dev/null @@ -1,46 +0,0 @@ -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import Foundation - -public protocol VoronoiDebugging: class { - var notVisitedSites: [Site] { get set } - var visitedSites: [Site] { get set } - var sweeplineY: Double { get set } - var currentBreakpoint: Site? { get set } - var circles: [Circle] { get set } - var upcomingCircleEvents: [Site] { get set } - var container: Rectangle? { get set } - var arcs: [ - ( - parabola: Parabola, - lBound: Double, - rBound: Double - ) - ] { get set } - var box: Rectangle? { get set } - var potentialEdges: [LineSegment] { get set } - var numSteps: Int? { get set } - var curStep: Int { get set } -} diff --git a/Sources/FortunesAlgorithm/Diagram.swift b/Sources/FortunesAlgorithm/Diagram.swift old mode 100644 new mode 100755 index 98c4f62..9981e5a --- a/Sources/FortunesAlgorithm/Diagram.swift +++ b/Sources/FortunesAlgorithm/Diagram.swift @@ -1,26 +1,25 @@ -/* -MIT License +// MIT License +// +// Copyright (c) 2020 Oleksandr Glagoliev +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation @@ -50,13 +49,13 @@ public class Diagram { cells.removeAll() vertices.removeAll() } - } /// The vertex record of a vertex v stores the coordinates of v. /// It also stores a pointer IncidentEdge(v) to an arbitrary half‐edge that has v as its origin public typealias Vertex = Site +public typealias Point = Site /// Stores pointer to: @@ -80,7 +79,6 @@ public class Cell { public extension Cell { - /// Returns hell vertices of the cell func hullVerticesCCW() -> [Vertex] { var vertices: [Vertex] = [] diff --git a/Sources/FortunesAlgorithm/Event.swift b/Sources/FortunesAlgorithm/Event.swift index 75305de..09e5cdd 100755 --- a/Sources/FortunesAlgorithm/Event.swift +++ b/Sources/FortunesAlgorithm/Event.swift @@ -1,31 +1,25 @@ +// MIT License // -// Created by Oleksandr Glagoliev on 5/29/19. -// Copyright © 2019 Oleksandr Glagoliev. All rights reserved. +// Copyright (c) 2020 Oleksandr Glagoliev // +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation diff --git a/Sources/FortunesAlgorithm/FortuneSweep.swift b/Sources/FortunesAlgorithm/FortuneSweep.swift index 51bcdf8..8d19ed2 100755 --- a/Sources/FortunesAlgorithm/FortuneSweep.swift +++ b/Sources/FortunesAlgorithm/FortuneSweep.swift @@ -1,26 +1,25 @@ -/* -MIT License +// MIT License +// +// Copyright (c) 2020 Oleksandr Glagoliev +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation @@ -28,47 +27,103 @@ public class FortuneSweep { /// Service Data Structures private var eventQueue: PriorityQueue! private var beachline: Beachline! - private var sweepLineY = Double(0) + private var sweepLineY: Double = 0 { + didSet { + watcher?.updateSweepline(y: sweepLineY) + } + } private var firstSiteY: Double? - - private var container: Rectangle! + private var container: Rectangle! { + didSet { + watcher?.updateContainer(rectangle: container) + } + } private var clipper: Rectangle! + /// Debug Data structures + private var logger: FortuneSweepLogging? + private var watcher: FortuneSweepProgressWatching? + private var currentStep: Int = 0 { + didSet { + watcher?.step = currentStep + } + } + private var isTerminated: Bool! /// Result Data Structure - private(set) var diagram = Diagram() + private(set) var diagram: Diagram! - public init() { } + + /// Initialises new FortuneSweep instance + /// NB: `logger` and especially `watcher` will affect performance! + /// Use them only for debug purposes! + /// + /// - Parameters: + /// - logger: Optional. Calls `log` function when importand events happen + /// - watcher: Optional. **Affects performance!** Tracks diagram building process. May be used for visualisation as it includes useful scaffolding. + public init( + logger: FortuneSweepLogging? = nil, + watcher: FortuneSweepProgressWatching? = nil + ) { + self.logger = logger + self.watcher = watcher + } public func compute( sites: Set, diagram: inout Diagram, - clippingRect: Rectangle - ) { + clippingRect: Rectangle, + maxStepsCount: Int = -1 + ) -> Bool { self.diagram = diagram self.clipper = clippingRect - let filtered = sites - .filter { clipper.contains($0) } - .map { Event(point: $0) } + let filteredSites = sites.filter { clipper.contains($0) } + + let events = filteredSites.map { Event(point: $0) } + + /// Intermediate state + watcher?.prepare(sites: filteredSites, clipper: clippingRect) + /// Diagram is a whole plane. Do nothing - if filtered.isEmpty { return } + if events.isEmpty { + logger?.log("Computation done. No sites inside defined area!", level: .info) + return true + } + currentStep = 0 sweepLineY = 0 firstSiteY = nil beachline = Beachline() eventQueue = PriorityQueue( ascending: true, - startingValues: filtered + startingValues: events ) + isTerminated = false + logger?.log("\n\nComputation started!", level: .info) - var finished = false - while !finished { + while !eventQueue.isEmpty && currentStep != maxStepsCount { step() - finished = eventQueue.isEmpty } if eventQueue.isEmpty { terminate() + return true + } + return false + } + + + /// Runs one step of an algorithm + func debug_step() -> Bool { + step() + if eventQueue.isEmpty { + if isTerminated == false { + terminate() + } else { + logger?.log("Algorithm terminated", level: .info) + } + return true } + return false } /// Performs one step of the algorithm @@ -76,6 +131,8 @@ public class FortuneSweep { /// 2. Check the event type and process the event appropriately private func step() { if let event = eventQueue.pop() { + currentStep += 1 + logger?.log("\nStep: \(currentStep)", level: .info) switch event.kind { case .site: processSiteEvent(event) @@ -89,6 +146,9 @@ public class FortuneSweep { /// Processes **Site event** and performs all the necessary actions /// - Parameter event: **Site Event** to process private func processSiteEvent(_ event: Event) { + logger?.log("Site Event: \(event.point)", level: .info) + watcher?.siteEvent(site: event.point) + /// #Step 1: /// Update **Sweepline** position sweepLineY = event.point.y @@ -101,16 +161,17 @@ public class FortuneSweep { /// Case 1: (Always present once) /// Beachline is empty. Create beachline root Arc and return if beachline.isEmpty { + logger?.log("Site Event first occurence. Root arc inserted for Site: \(event.point)", level: .info) let root = beachline.insertRootArc(point: event.point) firstSiteY = event.point.y - let padding: Double = 20 + let padding: Double = 20 // Arbitrary padding to make sure that container contains clipping rect container = .rect(from: clipper, with: padding) -// container = clipper /// Create new **Cell** record in **Voronoi Diagram** container.expandToContainPoint(event.point) diagram.createCell(root) + watcher?.createCell(cell: root.cell) return } @@ -122,12 +183,15 @@ public class FortuneSweep { /// - *y* coordinate will lay somewhere far above the points. /// We replace *y* with an arbitrary value big enough to cover our case. (`yVal`) if firstSiteY == sweepLineY { + logger?.log("Site Event degenerate case (Existing Sites share Y coodinate (\(sweepLineY)) with new Site) for Site: \(event.point)", level: .warning) + container.expandToContainPoint(event.point) let yVal: Double = -1000000//.leastNormalMagnitude let arc = beachline.handleSpecialArcInsertionCase(event.point) /// 1. Create new **Cell** record in **Voronoi Diagram** diagram.createCell(arc) + watcher?.createCell(cell: arc.cell) /// 2. Create proper *HalfEdge* records. Arc with the same *y* can only appear /// to the right of existing one as in case of *y* coordinate is shared they are sorted by *x* @@ -138,7 +202,9 @@ public class FortuneSweep { arc.leftHalfEdge = diagram.createHalfEdge(arc.cell!) arc.leftHalfEdge?.origin = p makeTwins(prev.rightHalfEdge, arc.leftHalfEdge) - + + // Debug + watcher?.addHalfEdges(hes: [prev.rightHalfEdge!, arc.leftHalfEdge!]) /// There is no sense to check for circle event when we encounter degenerate case because all the sites are colinear return } @@ -156,6 +222,17 @@ public class FortuneSweep { /// Create new **Cell** record in **Voronoi Diagram** container.expandToContainPoint(event.point) diagram.createCell(newArc) + watcher?.createCell(cell: newArc.cell) + + /// Notify `intermediate` if needed + if let intermediate = self.watcher { + let parabola = Parabola(focus: newArc.prev!.point!, directrixY: sweepLineY) + let breakPoint = Point( + x: event.point.x, + y: parabola.resolve(x: event.point.x) + ) + intermediate.updateCurentBreakpoint(point: breakPoint) + } /// #Step 3: /// If the arc we broke has circle event, than this event is false-alarm and has to be removed @@ -213,6 +290,9 @@ public class FortuneSweep { prev.rightHalfEdge = lTwin next.leftHalfEdge = rTwin + + watcher?.addHalfEdges(hes: [lhe, lTwin, rhe, rTwin]) + logger?.log("Site Event degenerate case (Breapoint has the same X coordinate as a Site: \(event.point)", level: .warning) } else { /// Regular and most likely case. Here we break the arc, create **HalfEdge** records and set proper pointers between them next.cell = prev.cell @@ -225,6 +305,12 @@ public class FortuneSweep { newArc.rightHalfEdge = newArc.leftHalfEdge next.leftHalfEdge = prev.rightHalfEdge + + watcher?.addHalfEdges(hes: [prev.rightHalfEdge!, newArc.leftHalfEdge!]) + } + + if let watcher = self.watcher { + watcher.updateBeachline(arcs: beachline.getArcs()) } } @@ -277,12 +363,19 @@ public class FortuneSweep { nextArc.leftHalfEdge = nextLHE makeTwins(prevArc.rightHalfEdge, nextArc.leftHalfEdge) + + // Debug + watcher?.createVertex(vertex: vertex) + watcher?.addHalfEdges(hes: [prevRHE, nextLHE]) } /// Processes circle event and performs all the necessary actions /// - Parameter event: **Circle Event** private func processCircleEvent(_ event: Event) { + logger?.log("Circle Event: \(event.point)", level: .info) + watcher?.circleEvent(point: event.point) + guard let arc = event.arc, let left = arc.prev, let right = arc.next @@ -319,6 +412,10 @@ public class FortuneSweep { /// Do the same for the triple where the former right neighbor is the middle arc. createCircleEvent(left) createCircleEvent(right) + + if let watcher = self.watcher { + watcher.updateBeachline(arcs: beachline.getArcs()) + } } /// Creates circle event for the coresponding **Arc** in the **Beachline** @@ -342,6 +439,9 @@ public class FortuneSweep { arc.event = event eventQueue.push(event) + + logger?.log("Create Circle Event for Arc: \(arc.point!)", level: .info) + watcher?.addUpcomingCircleEvent(circle: event.circle!) } /// Removes circle event from the **Priority Queue** and removes event from the **Arc** @@ -355,6 +455,9 @@ public class FortuneSweep { return } + watcher?.removeFalseAlarmCircleEvent(circle: event.circle!) + logger?.log("Remove Circle Event for Arc: \(arc.point!)", level: .info) + eventQueue.removeAll(event) arc.event = nil } @@ -365,9 +468,8 @@ public class FortuneSweep { /// 2. Complete incomplete cells /// 3. Clip cells to clipping rectangle private func terminate() { -// if diagram.cells.count == 1 { -// return -// } + isTerminated = true + logger?.log("Event Queue is empty. Diagram bounding started.", level: .info) // Step 1: // Bound incomplete arcs @@ -394,6 +496,8 @@ public class FortuneSweep { } } + watcher?.boundingDone() + for cell in diagram.cells { // Step 2: // Complete incomplete cells @@ -405,6 +509,9 @@ public class FortuneSweep { // Clip cells clipCell(cell, clippingRect: clipper) } + + watcher?.workDone() + logger?.log("Done!", level: .info) } /// Some of the cells will not be completed (Are not looped linked list of half-edges) @@ -489,6 +596,7 @@ public class FortuneSweep { connect(prev: cell.outerComponent, next: he) cell.outerComponent = he + watcher?.addHalfEdges(hes: [he]) } connect(prev: cell.outerComponent, next: firstHE) assert(cell.outerComponent?.destination == firstHE?.origin) @@ -503,7 +611,8 @@ public class FortuneSweep { var finish = false while !finish { guard let segmentToClip = he?.toSegment() else { - fatalError("[FATAL ERROR]: Cannot create segment from the `HalfEdge`!") + logger?.log("Fatal Error! Malformed Half-Edge!", level: .critical) + fatalError() } let (isOriginClipped, isDestinationClipped, segment) = lb_clip(segmentToClip, clipper: clippingRect.toClipper()) @@ -578,6 +687,8 @@ public class FortuneSweep { connect(prev: he, next: newHE) he = newHE + + watcher?.addHalfEdges(hes: [newHE]) } he.destination = end return (head, he) @@ -652,26 +763,6 @@ public class FortuneSweep { // MARK: - Helpers and extensions - -extension FortuneSweep { - func run(maxSteps: Int) { - var curStep = 0 - if maxSteps > 0 { - while curStep != maxSteps { - step() - curStep += 1 - } - } else { - while !eventQueue.isEmpty { - step() - } - } - - if eventQueue.isEmpty { - terminate() - } - } -} - extension Site { var vector: Vector2D { Vector2D(dx: x, dy: y) @@ -680,10 +771,35 @@ extension Site { extension Vector2D { var normal: Vector2D { - return Vector2D(dx: -dy, dy: dx) + Vector2D(dx: -dy, dy: dx) } var point: Site { - return Site(x: dx, y: dy) + Site(x: dx, y: dy) + } +} + +public struct BeachlineSegment { + let parabola: Parabola + let lBoundX: Double + let rBoundX: Double +} + +extension Beachline { + public func getArcs() -> [BeachlineSegment] { + var arcs = [BeachlineSegment]() + var arc = minimum + while arc != nil { + let (lb, rb) = arc!.bounds(sweeplineY) + arcs.append( + BeachlineSegment( + parabola: Parabola(focus: arc!.point!, directrixY: sweeplineY), + lBoundX: lb, + rBoundX: rb + ) + ) + arc = arc?.next + } + return arcs } } diff --git a/Sources/FortunesAlgorithm/FortuneSweepLogging.swift b/Sources/FortunesAlgorithm/FortuneSweepLogging.swift new file mode 100755 index 0000000..388b85e --- /dev/null +++ b/Sources/FortunesAlgorithm/FortuneSweepLogging.swift @@ -0,0 +1,28 @@ +// +// Logging.swift +// Voronoi +// +// Created by Oleksandr Glagoliev on 28.03.2020. +// Copyright © 2020 Oleksandr Glagoliev. All rights reserved. +// + +import Foundation + + +/// <#Description#> +public enum FortuneSweppLogLevel { + case info + case warning + case error + case critical +} + + +public protocol FortuneSweepLogging { + + /// Depending on implemntation prints/saves log messages + /// - Parameters: + /// - text: Log message + /// - level: Log level + func log(_ message: String, level: FortuneSweppLogLevel) +} diff --git a/Sources/FortunesAlgorithm/FortuneSweepProgressWatching.swift b/Sources/FortunesAlgorithm/FortuneSweepProgressWatching.swift new file mode 100755 index 0000000..5f93703 --- /dev/null +++ b/Sources/FortunesAlgorithm/FortuneSweepProgressWatching.swift @@ -0,0 +1,93 @@ +// MIT License +// +// Copyright (c) 2020 Oleksandr Glagoliev +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + + +import Foundation + +public protocol FortuneSweepProgressWatching: class { + + /// Depicts current step of an algorithm + var step: Int { get set } + + /// Called when algorithm is ready to work + /// - Parameter sites: Same as Fortunes Algorithm input + /// - Parameter clipper: Clipping rectangle + func prepare(sites: Set, clipper: Rectangle) + + + /// Called when sweepline changes position + /// - Parameter y: New sweepline Y position + func updateSweepline(y: Double) + + /// Called when Site Event occured + /// - Parameter site: Visited site + func siteEvent(site: Site) + + /// Called when Circle Event occured + /// - Parameter site: Visited site + func circleEvent(point: Point) + + + /// Called when bounding rectangle is changed + /// - Parameter rectangle: New Bounding rectangle + func updateContainer(rectangle: Rectangle) + + + /// Called when new breakpoint occured + /// - Parameter point: Breakpoint + func updateCurentBreakpoint(point: Point?) + + + /// Called when beachline is updated + /// - Parameter arcs: Arcs, currently present in the Beachline + func updateBeachline(arcs: [BeachlineSegment]) + + + /// Called when upcoming circle event is added to the Event Queue + /// - Parameter circle: Circle event circle + func addUpcomingCircleEvent(circle: Circle) + + + /// Called when Circle event is removed from Event Queue + /// - Parameter circle: Circle event circle + func removeFalseAlarmCircleEvent(circle: Circle) + + + /// Called when new Vertex is created + /// - Parameter vertex: Vertex + func createVertex(vertex: Vertex) + + /// Called when new Cell is added to the diagram + /// - Parameter cell: Cell + func createCell(cell: Cell) + + /// Called when HalfEdges are added to the diagram + /// - Parameter hes: List of recently added HalfEdges + func addHalfEdges(hes: [HalfEdge]) + + /// Called when Cells bounding is done + func boundingDone() + + /// Called when algorithm finished working + func workDone() +} diff --git a/Sources/FortunesAlgorithm/Geometry/Circle.swift b/Sources/FortunesAlgorithm/Geometry/Circle.swift index 49c0f22..e70a0d3 100755 --- a/Sources/FortunesAlgorithm/Geometry/Circle.swift +++ b/Sources/FortunesAlgorithm/Geometry/Circle.swift @@ -1,42 +1,36 @@ +// MIT License // -// Created by Oleksandr Glagoliev on 17/06/2019. -// Copyright © 2019 Oleksandr Glagoliev. All rights reserved. +// Copyright (c) 2020 Oleksandr Glagoliev // +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation // MARK: - Circle public struct Circle { - public let center: Site + public let center: Point public let radius: Double /// Defines circle by three points /// See: https://www.xarg.org/2018/02/create-a-circle-out-of-three-points/ - public init?(p1: Site, p2: Site, p3: Site) { + public init?(p1: Point, p2: Point, p3: Point) { let x1 = p1.x let y1 = p1.y let x2 = p2.x @@ -63,7 +57,7 @@ public struct Circle { let x = -b / (2 * a) let y = -c / (2 * a) - center = Site(x: x, y: y) + center = Point(x: x, y: y) radius = hypot(x - x1, y - y1) } @@ -72,7 +66,7 @@ public struct Circle { /// - Parameters: /// - center: Circle origin (center) /// - radius: Circle radius - public init(center: Site, radius: Double) { + public init(center: Point, radius: Double) { self.center = center self.radius = radius } @@ -80,8 +74,8 @@ public struct Circle { extension Circle { // Returns a point with maximum *Y* coordinate - public var bottomPoint: Site { - Site( + public var bottomPoint: Point { + Point( x: center.x, y: center.y + radius ) diff --git a/Sources/FortunesAlgorithm/Geometry/LiangBarsky.swift b/Sources/FortunesAlgorithm/Geometry/LiangBarsky.swift old mode 100644 new mode 100755 index 34217f4..2493d3a --- a/Sources/FortunesAlgorithm/Geometry/LiangBarsky.swift +++ b/Sources/FortunesAlgorithm/Geometry/LiangBarsky.swift @@ -1,34 +1,25 @@ +// MIT License // -// LiangBarsky.swift -// FortunesAlgorithm +// Copyright (c) 2020 Oleksandr Glagoliev // -// Created by Oleksandr Glagoliev on 2/16/20. -// Copyright © 2020 Oleksandr Glagoliev. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation diff --git a/Sources/FortunesAlgorithm/Geometry/LineSegment.swift b/Sources/FortunesAlgorithm/Geometry/LineSegment.swift index 953f96a..b6dea0d 100755 --- a/Sources/FortunesAlgorithm/Geometry/LineSegment.swift +++ b/Sources/FortunesAlgorithm/Geometry/LineSegment.swift @@ -1,34 +1,25 @@ +// MIT License // -// LineCut.swift -// FortuneSweep +// Copyright (c) 2020 Oleksandr Glagoliev // -// Created by Oleksandr Glagoliev on 9/21/19. -// Copyright © 2019 Oleksandr Glagoliev. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation diff --git a/Sources/FortunesAlgorithm/Geometry/Parabola.swift b/Sources/FortunesAlgorithm/Geometry/Parabola.swift index cd130a9..f4523f1 100755 --- a/Sources/FortunesAlgorithm/Geometry/Parabola.swift +++ b/Sources/FortunesAlgorithm/Geometry/Parabola.swift @@ -1,31 +1,25 @@ +// MIT License // -// Created by Oleksandr Glagoliev on 17/06/2019. -// Copyright © 2019 Oleksandr Glagoliev. All rights reserved. +// Copyright (c) 2020 Oleksandr Glagoliev // +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation diff --git a/Sources/FortunesAlgorithm/Geometry/Precision.swift b/Sources/FortunesAlgorithm/Geometry/Precision.swift index 1e48a47..6e3489e 100755 --- a/Sources/FortunesAlgorithm/Geometry/Precision.swift +++ b/Sources/FortunesAlgorithm/Geometry/Precision.swift @@ -1,3 +1,25 @@ +// MIT License +// +// Copyright (c) 2020 Oleksandr Glagoliev +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + import Foundation let eps: Double = 1e-7 diff --git a/Sources/FortunesAlgorithm/Geometry/Rectangle.swift b/Sources/FortunesAlgorithm/Geometry/Rectangle.swift index e7150e7..3236e43 100755 --- a/Sources/FortunesAlgorithm/Geometry/Rectangle.swift +++ b/Sources/FortunesAlgorithm/Geometry/Rectangle.swift @@ -1,31 +1,25 @@ +// MIT License // -// Created by Oleksandr Glagoliev on 9/22/19. -// Copyright © 2019 Oleksandr Glagoliev. All rights reserved. +// Copyright (c) 2020 Oleksandr Glagoliev // +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation diff --git a/Sources/FortunesAlgorithm/Geometry/Site.swift b/Sources/FortunesAlgorithm/Geometry/Site.swift old mode 100644 new mode 100755 index e22a286..4d0b479 --- a/Sources/FortunesAlgorithm/Geometry/Site.swift +++ b/Sources/FortunesAlgorithm/Geometry/Site.swift @@ -1,34 +1,25 @@ +// MIT License // -// Site.swift -// FortunesAlgorithm +// Copyright (c) 2020 Oleksandr Glagoliev // -// Created by Oleksandr Glagoliev on 3/1/20. -// Copyright © 2020 Oleksandr Glagoliev. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation @@ -45,6 +36,12 @@ public struct Site { } } +extension Site: CustomStringConvertible { + public var description: String { + return "(x: \(x), y: \(y))" + } +} + extension Site: Hashable { public static func == (lhs: Site, rhs: Site) -> Bool { lhs.x == rhs.x diff --git a/Sources/FortunesAlgorithm/Geometry/Size.swift b/Sources/FortunesAlgorithm/Geometry/Size.swift index 0ee2712..4474514 100755 --- a/Sources/FortunesAlgorithm/Geometry/Size.swift +++ b/Sources/FortunesAlgorithm/Geometry/Size.swift @@ -1,31 +1,25 @@ +// MIT License // -// Created by Oleksandr Glagoliev on 17/06/2019. -// Copyright © 2019 Oleksandr Glagoliev. All rights reserved. +// Copyright (c) 2020 Oleksandr Glagoliev // +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation diff --git a/Sources/FortunesAlgorithm/Geometry/Vector.swift b/Sources/FortunesAlgorithm/Geometry/Vector.swift index b963b5a..28ba0a2 100755 --- a/Sources/FortunesAlgorithm/Geometry/Vector.swift +++ b/Sources/FortunesAlgorithm/Geometry/Vector.swift @@ -1,33 +1,25 @@ +// MIT License // -// Vector2D.swift +// Copyright (c) 2020 Oleksandr Glagoliev // -// Created by fewlinesofcode.com on 2/6/19. -// Copyright © 2019 fewlinesofcode.com All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -/* -MIT License - -Copyright (c) 2020 Oleksandr Glagoliev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ import Foundation diff --git a/Tests/FortunesAlgorithmTests/FortunesAlgorithmTests.swift b/Tests/FortunesAlgorithmTests/FortunesAlgorithmTests.swift old mode 100644 new mode 100755 diff --git a/Tests/FortunesAlgorithmTests/XCTestManifests.swift b/Tests/FortunesAlgorithmTests/XCTestManifests.swift old mode 100644 new mode 100755 diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift old mode 100644 new mode 100755