My goal is to check if a point is inside a region. The code below illustrates a sample with the region defined with an Envelope struct.
Sample points along the border, inside and outside of the region are also defined.
all is then depicted using "Chart"
To check if the point is inside or not, I construct a Path from the "Envelope" points and than check if this path.contains(the point).
Some points that are on the border are found to be outside, while others are inside. What am I missing here? Any ideas?
import SwiftUI
import Charts
struct Envelope:Identifiable {
let id=UUID()
var x:Double
var y:Double
}
struct Point:Identifiable {
let id=UUID()
let point:CGPoint
}
struct ContentView: View {
let envelope:[Envelope]=[Envelope(x: 1.0, y: 1.0),
Envelope(x: 1.0, y: 2.0),
Envelope(x: 2.0, y: 2.0),
Envelope(x: 2.0, y: 1.0),
Envelope(x: 1.0, y: 1.0)
]
let pointToCheck1=CGPoint(x: 1.5, y: 1.5)
let pointToCheck2=CGPoint(x: 1.0, y: 2.0)
let pointToCheck3=CGPoint(x: 2.0, y: 2.0)
let pointToCheck4=CGPoint(x: 2.0, y: 1.0)
let pointToCheck5=CGPoint(x: 1.0, y: 1.0)
let pointToCheck6=CGPoint(x: 1.5, y: 1.0)
let pointToCheck7=CGPoint(x: 1.0, y: 1.5)
let pointToCheck8=CGPoint(x: 2.0, y: 1.5)
let pointToCheck9=CGPoint(x: 1.5, y: 2.0)
let pointToCheck10=CGPoint(x: 1.5, y: 2.1)
var points:[Point] {
[Point(point: pointToCheck1),
Point(point: pointToCheck2),
Point(point: pointToCheck3),
Point(point: pointToCheck4),
Point(point: pointToCheck5),
Point(point: pointToCheck6),
Point(point: pointToCheck7),
Point(point: pointToCheck8),
Point(point: pointToCheck9),
Point(point: pointToCheck10)]
}
var body: some View {
ZStack {
Chart {
ForEach(envelope) { item in
LineMark (x: .value("", item.x),
y: .value("", item.y)
).lineStyle(by: .value("", "CG Limit"))
}
ForEach(points) { point in
PointMark (x: .value("", Double(point.point.x)),
y: .value("", Double(point.point.y)))
.foregroundStyle(Color.orange)
.annotation {
Text("\(checkIntersection(point.point)) \(point.point)")
}
}
}
.chartXScale(domain: [0.7, 2.3])
.chartYScale(domain: [0.7, 2.3])
}
}
private func checkIntersection(_ point:CGPoint)->String {
var toReturn="Outside"
var pathObject=Path()
var isFirst=true
for sort in envelope {
let cgPoint=CGPoint(x: sort.x, y: sort.y)
if isFirst {
pathObject.move(to: cgPoint)
isFirst=false
}else{
pathObject.addLine(to: cgPoint)
}
}
if pathObject.contains(point) {
toReturn="Inside"
}
return toReturn
}
}
I may have found a solution. Instead of using Path(), I tried UIBezierPath() which returns my expected result.
private func checkIntersection(_ point:CGPoint)->String {
var toReturn="Outside"
var pathObject=UIBezierPath()
var isFirst=true
for sort in envelope {
let cgPoint=CGPoint(x: sort.x, y: sort.y)
if isFirst {
pathObject.move(to: cgPoint)
isFirst=false
}else{
pathObject.addLine(to: cgPoint)
}
}
if pathObject.contains(point) {
toReturn="Inside"
}
return toReturn
}