Why is my lineString not converting to mapShape in geoSwift - (only happens with one specific search), could be external library bug? - swift

Im using the GEOSwift Library: https://github.com/GEOSwift/GEOSwift
My best guess is that if you look at the string image linked, it looks as if its not a proper circle, so maybe it is a bug in the library? But i am not at all sure about this!
Im having an issue only when i enter one specific linestring.
My app takes an array of route coordinates, converts them into WKT String (representing a line). It then Creates a buffer around this line, then converts this into a mapShape.
It runs fine, until i search one specific route.
It fails here:
func bufferPolyline(routeCoords: [CLLocationCoordinate2D], completion: #escaping (_ bufferCoordsArray: [LatLng]) -> ()) {
var wktString = ""
var i = 0
while i < routeCoords.count {
let lat = routeCoords[i].latitude
let lng = routeCoords[i].longitude
if i == routeCoords.count-1 {
let wktLast = " \(lng) \(lat)"
wktString += "\(wktLast)"
i += 1
}
if i >= 1 && i <= routeCoords.count-2 {
let wktMid = " \(lng) \(lat),"
wktString += "\(wktMid)"
i += 1
}
if i == 0 {
let wktFirst = "\(lng) \(lat),"
wktString += "\(wktFirst)"
i += 1
}
}
let linestring = Geometry.create("LINESTRING(\(wktString))")!
let string = linestring.buffer(width: 0.05)!
guard let shapeLine = string.mapShape() as? MKPolygon else {
preconditionFailure() // FAILURE HAPPENS HERE.
}
}
Here are links to images to see how it looks:
LineString - https://imgur.com/a/7OLPZkM
String - https://imgur.com/a/KJRfpRX
the linestring, and string values are still coming through even when shapeLine doesnt initialise so im struggling to see where im going wrong. They also seem to be formatted the same way.
I tried to google for a WKT String validator, but didnt find one, but i assume it should be ok, as i return multiple other searches with no issues. (i.e. the shapeLine returns a value)
My question is: does this look like a problem in my code, or a possible bug of the library? (i have little faith in my code!)

Related

VNRecognizeTextRequest digital / seven-segment numbers

I basically followed this great tutorial on VNRecognizeTextRequest and modified some things:
https://bendodson.com/weblog/2019/06/11/detecting-text-with-vnrecognizetextrequest-in-ios-13/
I am trying to recognise text from devices with seven-segment-style displays which seems to get a bit tricky for this framework. Often it works, but numbers with comma are hard and if there's a a gap as well. I'm wondering whether there is the possibility to "train" this recognition engine. Another possibility might be to somehow tell it to specifically look for numbers, maybe then it can focus more processing power on that instead of generically looking for text?
I use this modified code for the request:
ocrRequest = VNRecognizeTextRequest { (request, error) in
guard let observations = request.results as? [VNRecognizedTextObservation] else { return }
for observation in observations {
guard let topCandidate = observation.topCandidates(1).first else { continue }
let topCandidateText = topCandidate.string
if let float = Float(topCandidateText), topCandidate.confidence > self.bestConfidence {
self.bestCandidate = float
self.bestConfidence = topCandidate.confidence
}
}
if self.bestConfidence >= 0.5 {
self.captureSession?.stopRunning()
DispatchQueue.main.async {
self.found(measurement: self.bestCandidate!)
}
}
}
ocrRequest.recognitionLevel = .accurate
ocrRequest.minimumTextHeight = 1/10
ocrRequest.recognitionLanguages = ["en-US", "en-GB"]
ocrRequest.usesLanguageCorrection = true
There are 3 global variables in this class regarding the text recognition:
private var ocrRequest = VNRecognizeTextRequest(completionHandler: nil)
private var bestConfidence: Float = 0
private var bestCandidate: Float?
Thanks in advance for your answers, even though this is not directly code-related, but more concept-related (i.e. "am I doing something wrong / did I overlook an important feature?" etc.).
Example image that work:
Example that half works:
(recognises 58)
Example that does not work:
(it has a very low confidence for "91" and often thinks it's just 9 or 9!)

Swift 4.2 computed variable [String:Bool] does not assign value correctly

[MacOS 10.14.1, Xcode 10.1, Swift 4.2]
I'm working on creating a getopt style CLI argument processor whilst practising Swift. In my design, I decided to create a computed variable, represented as a [String:Bool] dictionary, that can be checked to see if an option (key) is just a switch (value = true) or whether it may include parameters (value = false). So I've written the code below, all of which is, at the moment, in my small (300 lines) main.swift file.
The code works correctly in a playground, but in my Swift Xcode project, whilst the dictionary's keys are correct, values are always false and inconsistent with the printed messages.
let options = "cwt:i:o:"
//lazy var optionIsSwitch : [String:Bool] = { (This will be moved to a class)
var optionIsSwitch : [String:Bool] = {
var tmpOptionIsSwitch : [String:Bool] = [:]
let optionsStrAsArray = Array(options)
let flags = Array(options.filter { !":".contains($0) } )
tmpOptionIsSwitch.reserveCapacity(flags.count)
for thisOption in 0...flags.count-1 {
var posInOptionsStr = 0
while posInOptionsStr < optionsStrAsArray.count-1 && flags[thisOption] != optionsStrAsArray[posInOptionsStr] {
posInOptionsStr += 1
}
if posInOptionsStr < optionsStrAsArray.count-1 && optionsStrAsArray[posInOptionsStr+1] == ":" {
tmpOptionIsSwitch[String(flags[thisOption])] = false
print("\(flags[thisOption]) is FALSE")
} else {
tmpOptionIsSwitch[String(flags[thisOption])] = true
print("\(flags[thisOption]) is TRUE")
}
}
return tmpOptionIsSwitch
}()
I've stepped through the code in my project to observe the execution sequence, and found it to be correct. As per the first image, tmpOptionIsSwitch returns a dictionary containing the right keys but all the values are set to false, which is inconsistent with the print statements.
As part of my debugging activities, I copied the above code into a Swift Playground where I found it gave the correct results, as per the image below.
Has anyone has such an issue? Is there something I've done wrong?

Performing functions with valueForKey

I am trying to get my app to perform functions. I have two attributes per item (quantity and price) that I want to multiply together and then total for all the didSelectRow items on the list. There is two sections on my tableView. Section 0 is regular and moved to section 1 with didSelectRow. (I only explain this because it comes into play further down)
My code so far is...
`func cartTotalFunc() {
itemFetchRequest().returnsObjectsAsFaults = false
do {
let results = try moc.executeFetchRequest(itemFetchRequest())
print("===\(results)")
// Calculate the grand total.
var grandTotal = 0
for order in results {
let SLP = order.valueForKey("slprice") as! Int
let SLQ = order.valueForKey("slqty") as! Int
grandTotal += SLP * SLQ
}
print("\(grandTotal)")
cartTotal.text = "$\(grandTotal)" as String
} catch let error as NSError {
print(error)
}
}
`
slprice and slqty are strings in Core Data. I am trying to cast them as Int so they will do the arithmetic. I had this working but it totaled every item instead of only the crossed off ones (section 1). I gave it a rest for a while and now when I come back to try to work on it again Xcode is giving me an error of, "can not Could not cast value of type 'NSTaggedPointerString' (0x104592ae8) to 'NSNumber' (0x1051642a0)."
Can anyone help with this, please?

Get the name of a connected screen Swift

Does anyone know of a way to get the screen name, or model name/number from a display that is connected to the system? I've been looking around for quite some time to see if there is a way to do this. The only method I've seen anyone post only works with a deprecated API (CGDisplayIOServicePort), (and there's not replacement listed for that API), so that isn't really an option.
Basically, I am wanting to give the user a list of connected screens to display the output of the app, and I feel like giving them a list of names of the displays would be much more elegant and nicer than whatever the ID is that is returned from NSScreen or CGGetActiveDisplayList, etc. It has to possible, when you go to the display preferences in OS X it gives you the names of the displays there. Anyone have any ideas?
macOS 10.15 Catalina introduced a new property localizedName for getting the external display name:
NSScreen.screens.forEach {
print($0.localizedName)
}
You can get the names of connected screens directly from IOReg
func screenNames() -> [String] {
var names = [String]()
var object : io_object_t
var serialPortIterator = io_iterator_t()
let matching = IOServiceMatching("IODisplayConnect")
let kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault,
matching,
&serialPortIterator)
if KERN_SUCCESS == kernResult && serialPortIterator != 0 {
repeat {
object = IOIteratorNext(serialPortIterator)
let info = IODisplayCreateInfoDictionary(object, UInt32(kIODisplayOnlyPreferredName)).takeRetainedValue() as NSDictionary as! [String:AnyObject]
if let productName = info["DisplayProductName"] as? [String:String],
let firstKey = Array(productName.keys).first {
names.append(productName[firstKey]!)
}
} while object != 0
}
IOObjectRelease(serialPortIterator)
return names
}
let names = screenNames()

Why in swift are variables option in a function but not in playground

I am puzzled. I need to compare product date codes. they look like 12-34-56. I wrote some code to break the parts up and compare them. this code works fin in the play ground. But when i make it a function in a view controller values come up NIL and i get a lot of "Optional("12-34-56")" values when printed to the log or viewed in a break. I tried unwrapping in many locations but nothing takes.? don't be confused by the variables date and month because they are not product codes can have 90 days and 90 months depending on the production machine used.
func compaireSerial(oldNumIn: NSString, newNumIn: String) -> Bool {
// take the parts of the number and compare the pics on at a time.
// Set up the old Num in chunks
let oldNum = NSString(string: oldNumIn)
let oldMonth = Int(oldNum.substringToIndex(2))
let oldDay = Int(oldNum.substringWithRange(NSRange(location: 3, length: 2)))
let oldYear = Int(oldNum.substringFromIndex(6))
print(oldMonth,oldDay, oldYear)
// Set up the new Num in chunks
let newNum = NSString(string: newNumIn)
let newMonth = Int(newNum.substringToIndex(2))
let newDay = Int(newNum.substringWithRange(NSRange(location: 3, length: 2)))
let newYear = Int(newNum.substringFromIndex(6))
print(newMonth, newDay, newYear)
// LETS Do the IF comparison steps.
if oldYear < newYear {
return true
} else if oldMonth < newMonth {
return true
} else if oldDay < newDay {
return true
} else {
return false
}
}
May thanks to any one. Im totally stumped
All Int() initializers with String parameters return always an optional Int.
The realtime result column in a Playground doesn't indicate the optional but printing it does.
let twentyTwo = Int("22") | 22
print(twentyTwo) | "Optional(22)\n"
I don't see how i can delete my question so ill post this to let others know it is fixed. Turns out the auction works okay but the NSUserDefaults value coming in was optional. So i was feeding the optional in. After unwrapping the NSUser value all works.