-
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bd22ba4
commit 654a885
Showing
11 changed files
with
340 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// | ||
// Bezier.c | ||
// | ||
// | ||
// Created by Michael Verges on 8/17/20. | ||
// | ||
|
||
#include "Bezier.h" | ||
|
||
/** | ||
* @brief a | ||
*/ | ||
void bezier_ctrl(const int size, const double *src_x, const double *src_y, | ||
double *ctrl1_x, double *ctrl1_y, | ||
double *ctrl2_x, double *ctrl2_y) { | ||
int prev = size - 1; | ||
int next = 1; | ||
for(int i = 0; i < size; i++) { | ||
double dx = src_x[prev] - src_x[next]; | ||
double dy = src_y[prev] - src_y[next]; | ||
double m = sqrt(dx * dx + dy * dy); | ||
dx /= m; | ||
dy /= m; | ||
|
||
double next_dx = src_x[i] - src_x[next]; | ||
double next_dy = src_y[i] - src_y[next]; | ||
double next_dist = sqrt(next_dx * next_dx + next_dy * next_dy); | ||
ctrl1_x[next] = src_x[i] - dx * next_dist / 3.0; | ||
ctrl1_y[next] = src_y[i] - dy * next_dist / 3.0; | ||
|
||
double prev_dx = src_x[i] - src_x[prev]; | ||
double prev_dy = src_y[i] - src_y[prev]; | ||
double prev_dist = sqrt(prev_dx * prev_dx + prev_dy * prev_dy); | ||
ctrl2_x[i] = src_x[i] + dx * prev_dist / 3.0; | ||
ctrl2_y[i] = src_y[i] + dy * prev_dist / 3.0; | ||
|
||
prev = (prev + 1) % size; | ||
next = (next + 1) % size; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// | ||
// Bezier.h | ||
// | ||
// | ||
// Created by Michael Verges on 8/17/20. | ||
// | ||
|
||
#ifndef Bezier_h | ||
#define Bezier_h | ||
|
||
#include <math.h> | ||
void bezier_ctrl(const int size, const double *src_x, const double *src_y, | ||
double *ctrl1_x, double *ctrl1_y, | ||
double *ctrl2_x, double *ctrl2_y); | ||
|
||
#endif /* Bezier_h */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// | ||
// AnimatableArray.swift | ||
// | ||
// | ||
// Created by Michael Verges on 8/14/20. | ||
// | ||
|
||
import SwiftUI | ||
import enum Accelerate.vDSP | ||
|
||
struct AnimatableArray: VectorArithmetic { | ||
|
||
var values: [Double] | ||
|
||
init(_ values: [Double]) { | ||
self.values = values | ||
} | ||
|
||
static var zero = AnimatableArray([0.0]) | ||
|
||
static func + (lhs: AnimatableArray, rhs: AnimatableArray) -> AnimatableArray { | ||
let count = min(lhs.values.count, rhs.values.count) | ||
return AnimatableArray(vDSP.add(lhs.values[0..<count], rhs.values[0..<count])) | ||
} | ||
|
||
static func += (lhs: inout AnimatableArray, rhs: AnimatableArray) { | ||
let count = min(lhs.values.count, rhs.values.count) | ||
vDSP.add(lhs.values[0..<count], rhs.values[0..<count], result: &lhs.values[0..<count]) | ||
} | ||
|
||
static func - (lhs: AnimatableArray, rhs: AnimatableArray) -> AnimatableArray { | ||
let count = min(lhs.values.count, rhs.values.count) | ||
return AnimatableArray(vDSP.subtract(lhs.values[0..<count], rhs.values[0..<count])) | ||
} | ||
|
||
static func -= (lhs: inout AnimatableArray, rhs: AnimatableArray) { | ||
let count = min(lhs.values.count, rhs.values.count) | ||
vDSP.subtract(lhs.values[0..<count], rhs.values[0..<count], result: &lhs.values[0..<count]) | ||
} | ||
|
||
mutating func scale(by rhs: Double) { | ||
vDSP.multiply(rhs, values, result: &values) | ||
} | ||
|
||
var magnitudeSquared: Double { | ||
vDSP.sum(vDSP.multiply(values, values)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// | ||
// File.swift | ||
// | ||
// | ||
// Created by Michael Verges on 8/17/20. | ||
// | ||
|
||
import CoreGraphics | ||
import CLiquid | ||
|
||
struct ControlPoints { | ||
|
||
var x1: [Double] | ||
var y1: [Double] | ||
var x2: [Double] | ||
var y2: [Double] | ||
|
||
init(x: [Double], y: [Double]) { | ||
assert( | ||
x.count == y.count, | ||
"Expected matching pairs for x and y, but found " | ||
+ "\(x.count) x points and \(y.count) y points") | ||
let count = x.count | ||
var x1: [Double] = [Double](repeating: 0, count: count) | ||
var y1: [Double] = [Double](repeating: 0, count: count) | ||
var x2: [Double] = [Double](repeating: 0, count: count) | ||
var y2: [Double] = [Double](repeating: 0, count: count) | ||
bezier_ctrl(Int32(count), x, y, &x1, &y1, &x2, &y2) | ||
self.x1 = x1 | ||
self.y1 = y1 | ||
self.x2 = x1 | ||
self.y2 = y1 | ||
} | ||
|
||
init(_ points: [CGPoint]) { | ||
let count = points.count | ||
let x = points.map { Double($0.x) } | ||
let y = points.map { Double($0.y) } | ||
var x1: [Double] = [Double](repeating: 0, count: count) | ||
var y1: [Double] = [Double](repeating: 0, count: count) | ||
var x2: [Double] = [Double](repeating: 0, count: count) | ||
var y2: [Double] = [Double](repeating: 0, count: count) | ||
bezier_ctrl(Int32(count), x, y, &x1, &y1, &x2, &y2) | ||
self.x1 = x1 | ||
self.y1 = y1 | ||
self.x2 = x1 | ||
self.y2 = y1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// | ||
// Array.swift | ||
// | ||
// | ||
// Created by Michael Verges on 8/17/20. | ||
// | ||
|
||
import Foundation | ||
|
||
extension Array { | ||
func randomElements(_ n: Int) -> [Element] { | ||
var copy = self | ||
var selection: [Element] = [] | ||
let range = count / n | ||
for _ in 0..<n { | ||
let max: Int = Swift.min(range, copy.count) | ||
let index = Int.random(in: 0...(max - 1)) | ||
selection.append(copy[index]) | ||
copy.removeFirst(range) | ||
if copy.isEmpty { | ||
return selection | ||
} | ||
} | ||
return selection | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// | ||
// CGPath.swift | ||
// | ||
// | ||
// Created by Michael Verges on 8/17/20. | ||
// | ||
|
||
import CoreGraphics | ||
|
||
extension CGPath { | ||
func getPoints() -> [CGPoint] { | ||
var points: [CGPoint] = [] | ||
self.applyWithBlock { (element) in | ||
points.append(element.pointee.points.pointee) | ||
} | ||
return points | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// | ||
// Interpolate.swift | ||
// | ||
// | ||
// Created by Michael Verges on 8/17/20. | ||
// | ||
|
||
import Accelerate | ||
|
||
extension Array where Element == Double { | ||
func interpolate(_ n: Int) -> [Double] { | ||
|
||
let stride = vDSP_Stride(1) | ||
|
||
var base: Double = 0 | ||
var end = Double(n - 1) | ||
var control = [Double](repeating: 0, count: count) | ||
vDSP_vgenD(&base, &end, &control, stride, vDSP_Length(count)) | ||
|
||
var result = [Double](repeating: 0, count: n) | ||
vDSP_vgenpD(self, stride, control, stride, &result, stride, vDSP_Length(n), vDSP_Length(self.count)) | ||
|
||
return result | ||
} | ||
} | ||
|
||
extension Array where Element == CGPoint { | ||
|
||
func interpolate(_ n: Int) -> (x: [Double], y: [Double]) { | ||
let x = self.map { Double($0.x) } | ||
let y = self.map { Double($0.y) } | ||
return (x.interpolate(n), y.interpolate(n)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// | ||
// Path.swift | ||
// | ||
// | ||
// Created by Michael Verges on 8/17/20. | ||
// | ||
|
||
import SwiftUI | ||
|
||
extension Path { | ||
|
||
@discardableResult | ||
mutating func smooth(_ points: [CGPoint]) -> Path { | ||
let controls = ControlPoints(points) | ||
self.move(to: points.last!) | ||
for i in 0..<points.count { | ||
self.addCurve( | ||
to: points[i], | ||
control1: CGPoint(x: controls.x1[i], y: controls.y1[i]), | ||
control2: CGPoint(x: controls.x2[i], y: controls.y2[i])) | ||
} | ||
return self | ||
} | ||
|
||
@discardableResult | ||
mutating func smooth(x: [Double], y: [Double]) -> Path { | ||
let controls = ControlPoints(x: x, y: y) | ||
move(to: CGPoint(x: x.last!, y: y.last!)) | ||
for i in 0..<x.count { | ||
addCurve( | ||
to: CGPoint(x: x[i], y: y[i]), | ||
control1: CGPoint(x: controls.x1[i], y: controls.y1[i]), | ||
control2: CGPoint(x: controls.x2[i], y: controls.y2[i])) | ||
} | ||
return self | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// | ||
// LiquidCircle.swift | ||
// | ||
// | ||
// Created by Michael Verges on 8/17/20. | ||
// | ||
|
||
import SwiftUI | ||
|
||
struct LiquidCircle: LiquidShape { | ||
|
||
struct Model: LiquidModel { | ||
var radians: AnimatableArray | ||
} | ||
static func generate(from model: Model) -> Model { | ||
let radians = generateRadians(model.radians.values.count) | ||
return Model(radians: AnimatableArray(radians)) | ||
} | ||
init(_ model: Model) { | ||
self.radians = model.radians | ||
} | ||
|
||
var radians: AnimatableArray | ||
|
||
var animatableData: AnimatableArray { | ||
get { radians } | ||
set { radians = newValue } | ||
} | ||
|
||
func path(in rect: CGRect) -> Path { | ||
|
||
Path { path in | ||
let points = self.points(in: rect) | ||
path.smooth(x: points.x, y: points.y) | ||
} | ||
} | ||
|
||
static func generateRadians(_ count: Int) -> [Double] { | ||
var results: [Double] = [] | ||
for i in 0..<count { | ||
let min = Double(i) / Double(count) * 2 * .pi | ||
let max = Double(i + 1) / Double(count) * 2 * .pi | ||
results.append(Double.random(in: min...max)) | ||
} | ||
|
||
let offset = Double.random(in: 0...(.pi)) | ||
return results.map { $0 + offset } | ||
} | ||
|
||
func points(in rect: CGRect) -> (x: [Double], y: [Double]) { | ||
var x: [Double] = [] | ||
var y: [Double] = [] | ||
x.reserveCapacity(radians.values.count) | ||
y.reserveCapacity(radians.values.count) | ||
let width = Double(rect.width) | ||
let height = Double(rect.height) | ||
let offset = (x: Double(rect.midX), y: Double(rect.midY)) | ||
for i in 0..<radians.values.count { | ||
x.append(offset.x + cos(radians.values[i]) * width / 2) | ||
y.append(offset.y + sin(radians.values[i]) * height / 2) | ||
} | ||
return (x, y) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters