lrtitze / swift-vectorboolean Goto Github PK
View Code? Open in Web Editor NEWA Swift iOS rewrite of Andy Finnell's VectorBoolean bezier path tools
License: MIT License
A Swift iOS rewrite of Andy Finnell's VectorBoolean bezier path tools
License: MIT License
The project in its current state specifically says "for iOS", would it be ok to change this and add framework targets for iOS, watchOS and tvOS?
Anyone working it? If no I may have to.
Hi, I set two paths as follows.
let path = UIBezierPath()
path.move(to: CGPoint(x: 445, y: 359))
path.addCurve(to: CGPoint(x: 381, y: 423), controlPoint1: CGPoint(x: 445, y: 394.3462239872), controlPoint2: CGPoint(x: 416.3462239872, y: 423))
path.addCurve(to: CGPoint(x: 317, y: 359), controlPoint1: CGPoint(x: 345.6537760128, y: 423), controlPoint2: CGPoint(x: 317, y: 394.3462239872))
path.addCurve(to: CGPoint(x: 381, y: 295), controlPoint1: CGPoint(x: 317, y: 323.6537760128), controlPoint2: CGPoint(x: 345.6537760128, y: 295))
path.addCurve(to: CGPoint(x: 445, y: 359), controlPoint1: CGPoint(x: 416.3462239872, y: 295), controlPoint2: CGPoint(x: 445, y: 323.6537760128))
path.close()
let path1 = UIBezierPath()
path1.move(to: CGPoint(x: 396.188153789188, y: 421.1869913808138))
path1.addCurve(to: CGPoint(x: 354, y: 361), controlPoint1: CGPoint(x: 371.580991406671, y: 412.2674684341148), controlPoint2: CGPoint(x: 354, y: 388.6868644969018))
path1.addCurve(to: CGPoint(x: 402.8118787893286, y: 298.813008615249), controlPoint1: CGPoint(x: 354, y: 330.8869397620923), controlPoint2: CGPoint(x: 374.7972348964752, y: 305.6313340004763))
path1.addCurve(to: CGPoint(x: 445, y: 359), controlPoint1: CGPoint(x: 427.419008593329, y: 307.7325315658853), controlPoint2: CGPoint(x: 445, y: 331.3131355030982))
path1.addCurve(to: CGPoint(x: 396.1881212105952, y: 421.1869913847696), controlPoint1: CGPoint(x: 445, y: 389.113060237935), controlPoint2: CGPoint(x: 424.2027651034871, y: 414.3686659995695))
path1.close()
And then I tried to get 'union', 'intersect' of these two paths.
Results are not correct.
'Union' result should be 'full circle'...
Anyone can fix this bug?
Thanks
In BezierGraph there's some code that punts on a quad curve. You should be able to handle the case by converting from a quadratic to cubic bezier representation, something like this:
/**
Initializes the receiver as a cubic curve representation of a quadratic curve from
p0 to p1 with a control point at cp0
*/
public init(p0: CGPoint, p1: CGPoint, cp0: CGPoint) {
self.p0 = p0; self.p1 = p1
// convert quadratic to cubic bezier
// see: http://stackoverflow.com/a/3162732
let twoThirds: CGFloat = 2.0/3.0
self.cp0 = p0 + twoThirds * (cp0 - p0)
self.cp1 = p1 + twoThirds * (cp0 - p1)
}
I'm using the fb_union
, fb_difference
functions to create a complex bezier path. I'm finding that there are many issues with these functions.
Here is code that generates a rectangle by combining a series of smaller rectangles:
var bezier = UIBezierPath()
for x in 20..<30 {
for y in 15..<20 {
let rect = CGRect(x: x * 10, y: y * 10, width: 11, height: 11)
let bezier2 = UIBezierPath(rect: rect)
bezier = bezier.fb_union(bezier2)
}
}
The width/height is 11 to create a little overlap. From the result I can see that this works, and creates what appears to be a larger rectangle (albeit with a complex single-shape geometry, once printed).
<UIBezierPath: 0x282f98780; <MoveTo {290.49999999999994, 201}>,
<LineTo {280.49999999999994, 201}>,
<LineTo {280.49999999999994, 200.99999999999997}>,
<LineTo {270.50000000000006, 201}>,
<LineTo {270.49999999999994, 200.99999999999997}>,
<LineTo {260.50000000000006, 201}>,
<LineTo {260.49999999999994, 201}>,
<LineTo {250.5, 201}>,
<LineTo {250.49999999999994, 201}>,
<LineTo {240.5, 201}>,
<LineTo {240.49999999999997, 201}>,
<LineTo {230.50000000000003, 201}>,
<LineTo {230.5, 201}>,
<LineTo {220.50000000000003, 201}>,
<LineTo {210.50000000000003, 201}>,
<LineTo {200, 201}>,
<LineTo {200, 190.50000000000003}>,
<LineTo {199.99999999999994, 190.50000000000003}>,
<LineTo {199.99999999999994, 180.5}>,
<LineTo {200, 170.5}>,
<LineTo {200, 170.50000000000003}>,
<LineTo {200, 160.50000000000003}>,
<LineTo {200, 150}>,
<LineTo {210.5, 150}>,
<LineTo {210.50000000000003, 150}>,
<LineTo {220.49999999999997, 150}>,
<LineTo {220.50000000000003, 150}>,
<LineTo {230.50000000000003, 150}>,
<LineTo {240.50000000000003, 150}>,
<LineTo {250.50000000000003, 150}>,
<LineTo {250.5, 150}>,
<LineTo {260.49999999999994, 150}>,
<LineTo {260.50000000000006, 150}>,
<LineTo {270.49999999999994, 150}>,
<LineTo {270.50000000000006, 150}>,
<LineTo {280.49999999999994, 150}>,
<LineTo {280.5, 150}>,
<LineTo {290.49999999999994, 150}>,
<LineTo {290.50000000000006, 150}>,
<LineTo {301, 150}>,
<LineTo {301, 160.50000000000003}>,
<LineTo {301, 170.50000000000003}>,
<LineTo {301, 180.50000000000003}>,
<LineTo {301, 190.50000000000003}>,
<LineTo {301, 201}>,
<LineTo {290.5, 201}>,
<Close>
Then I remove every other column, by only drawing columns on even rows:
var bezier = UIBezierPath()
for x in 20..<30 {
if floor(Double(x) / 2) != Double(x) / 2 {
continue
}
for y in 15..<20 {
let rect = CGRect(x: x * 10, y: y * 10, width: 11, height: 11)
let bezier2 = UIBezierPath(rect: rect)
bezier = bezier.fb_union(bezier2)
}
}
The result here is that some of the shapes which should be drawn, inexplicably aren't.
This is an example result - I'm only showing issues with fb_union
here, but this issue is very prevalent across uses of these functions. This can be tested using the attached sample project.
Would it make sense to add support for macOS?
This would require some type aliases, similarly as I've done in my BezierPath+Length project.
To be clear: I'd like to take this task upon me, but would like a green light before I start ๐ to make sure it fits the vision for the VectorBoolean project.
The update to Swift 4 is mostly fairly straight forward - only a few changes necessary. However, there's 1 thing that I'm not able to update myself, in CGPathBridge CGPath file:
typealias MyPathApplier = @convention(block) (UnsafePointer<CGPathElement>) -> Void
// Note: You must declare MyPathApplier as @convention(block), because
// if you don't, you get "fatal error: can't unsafeBitCast between
// types of different sizes" at runtime, on Mac OS X at least.
private func myPathApply(_ path: CGPath!, block: MyPathApplier) {
let callback: @convention(c) (UnsafeMutableRawPointer, UnsafePointer<CGPathElement>) -> Void = { (info, element) in
let block = unsafeBitCast(info, to: MyPathApplier.self)
block(element)
}
path.apply(info: unsafeBitCast(block, to: UnsafeMutableRawPointer.self), function: unsafeBitCast(callback, to: CGPathApplierFunction.self))
}
Xcode 10 throws an error on the last line, highlighting unsafeBitCast
:
Converting non-escaping value to 'T' may allow it to escape
Even with the Swift version set to 3.2, or updating it to 4.0 and then setting it to 4.0, it still won't let me build with this line existing. Perhaps an Xcode 10 issue, worth understanding.
When building the project in release mode I get 2 errors:
Undefined symbols for architecture arm64: "direct type metadata for ext.Swift_VectorBoolean.__ObjC.CGPath.Element", referenced from: l_get_field_types_LRTBezierPathWrapper in LRTBezierPathWrapper.o generic specialization <Swift._ArrayBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element> with Swift._ArrayBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element> : Swift._ArrayBufferType in Swift, ext.Swift_VectorBoolean.__ObjC.CGPath.Element, Swift.IndexingGenerator<Swift._ArrayBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element>> with Swift.IndexingGenerator<Swift._ArrayBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element>> : Swift.GeneratorType in Swift, ext.Swift_VectorBoolean.__ObjC.CGPath.Element, Swift.Int with Swift.Int : Swift.ForwardIndexType in Swift, Swift.Int with Swift.Int : Swift._SignedIntegerType in Swift, Swift.Int with Swift.Int : Swift._BuiltinIntegerLiteralConvertible in Swift, Swift.Int, Swift._SliceBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element> with Swift._SliceBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element> : Swift.Indexable in Swift and Swift._SliceBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element> : Swift.SequenceType in Swift, Swift.IndexingGenerator<Swift._SliceBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element>> with Swift.IndexingGenerator<Swift._SliceBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element>> : Swift.GeneratorType in Swift, ext.Swift_VectorBoolean.__ObjC.CGPath.Element, Swift.Int with Swift.Int : Swift.ForwardIndexType in Swift, Swift.Int with Swift.Int : Swift._SignedIntegerType in Swift, Swift.Int with Swift.Int : Swift._BuiltinIntegerLiteralConvertible in Swift, Swift.Int, Swift._SliceBuffer<ext.Swift_VectorBoolean.__ObjC.CGPath.Element>, ext.Swift_VectorBoolean.__ObjC.CGPath.Element, ext.Swift_VectorBoolean.__ObjC.CGPath.Element> of Swift._forceCreateUniqueMutableBuffer <A where A: Swift._ArrayBufferType> (inout A, newCount : Swift.Int, countForCapacity : Swift.Int) -> Swift._ContiguousArrayBuffer<A.Element> in LRTBezierPathWrapper.o ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
This seems to be related to the Swift optimization level, when setting it to None[-Onone], the build succeeds.
Is it ok to remove the old Objective-C method signatures?
e.g. the "- (void) removeCrossings" part in this example:
// 1298
//- (void) removeCrossings
fileprivate func removeCrossings()
Also, what does the number above the signature mean? (1298 in the example above)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.