I have a loop below that is supposed to detect if a view in an array of UIView's overlap with each other at all. If they do, then adjust their center value.
Each view is 25x25.
func drawCircles() {
for i in 0..<circles.count{
circles[i].center = getRandomPoint()
for j in 0..<circles.count{
if(i != j) {
let comparingCentre = circles[j].center
let dist = distance(comparingCentre, circles[i].center)
if dist <= 25 {
var newCenter = circles[i].center
var centersVector = CGVector(dx: newCenter.x - comparingCentre.x, dy: newCenter.y - comparingCentre.y)
//Circle width is 25
centersVector.dx *= 26 / dist
centersVector.dy *= 26 / dist
newCenter.x = comparingCentre.x + centersVector.dx
newCenter.y = comparingCentre.y + centersVector.dy
circles[i].center = newCenter
}
}
}
}
...
}
Below is the method for generating a random CGPoint that gets set to the view's center:
func getRandomPoint() -> CGPoint {
let viewMidX = self.circlesView.bounds.midX
let viewMidY = self.circlesView.bounds.midY
let xPosition = self.circlesView.frame.midX - viewMidX + CGFloat(arc4random_uniform(UInt32(viewMidX*2)))
let yPosition = self.circlesView.frame.midY - viewMidY + CGFloat(arc4random_uniform(UInt32(viewMidY*2)))
let point = CGPoint(x: xPosition, y: yPosition)
return point
}
And below is the method for determining the distance between two UIView's.
func distance(_ a: CGPoint, _ b: CGPoint) -> CGFloat {
let xDist = a.x - b.x
let yDist = a.y - b.y
return CGFloat(hypot(xDist, yDist))
}
However, I'm still experiencing, occasionally, when two view's will overlap each other (see the red-circled section below):

EDIT This is code that adds the circles to the view:
func generateCircles() {
numberOfCircles = Int.random(in: 1..<50)
let circleWidth = CGFloat(25)
let circleHeight = circleWidth
var i = 0
while i < numberOfCircles {
let circleView = CircleView(frame: CGRect(x: 0.0, y: 0.0, width: circleWidth, height: circleHeight))
let number = Int.random(in: 0..<2)
if number == 1 {
circleView.mainColor = .yellow
} else {
circleView.mainColor = .blue
}
circles.append(circleView)
i += 1
}
drawCircles()
}
Here's a quick option based on my comment above about moving the logic for comparing distance into creation of the random point: This can be cleaned up, but I didn't want to fully rewrite it and used as much of your code as possible.
In the generateCirles function I only changed how you init your CircleView
func generateCircles() {
numberOfCircles = Int.random(in: 1..<50)
let circleWidth = CGFloat(25)
let circleHeight = circleWidth
for _ in 0..<numberOfCircles {
let circleView = CircleView(frame: CGRect(origin: getRandomPoint(), size: (CGSize(width: circleWidth, height: circleHeight))))
let number = Int.random(in: 0..<2)
if number == 1 {
circleView.mainColor = .yellow
} else {
circleView.mainColor = .blue
}
circles.append(circleView)
}
drawCircles()
}
In the getRandomPoint I added a check to see if the new point is a valid point based on your existing distance logic:
func getRandomPoint() -> CGPoint {
let viewMidX = self.circlesView.bounds.midX
let viewMidY = self.circlesView.bounds.midY
let xPosition = self.circlesView.frame.midX - viewMidX + CGFloat(arc4random_uniform(UInt32(viewMidX*2)))
let yPosition = self.circlesView.frame.midY - viewMidY + CGFloat(arc4random_uniform(UInt32(viewMidY*2)))
let point = CGPoint(x: xPosition, y: yPosition)
if !validatePoint(point) {
return getRandomPoint()
}
return point
}
func validatePoint(_ point: CGPoint) -> Bool {
for circle in circles {
if distance(circle.frame.origin, point) <= 25 {
return false
}
}
return true
}
And I removed all of your code from drawCircles that you posted.
Here's what it looks like with 300 circles: (I used the view frame as the circlesView frame, so that's why the circles are over lapping with the screen bounds) This shouldn't be an issue for you, as I assume your circlesView frame is set to be smaller.

I think you should be able to do something like this:
let firstCircle = circles[i]
let secondCircle = circles[j]
let intersect = firstCircle.frame.intersection(secondCircle.frame)
if intersect.isNull {
// The circles do NOT overlap.
} else {
// The circles overlap. Handle accordingly.
}
Note that this doesn't handle the various edge cases such as comparing the same circles with each other, but this should simplify understanding if they overlap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With