判断 UIView 数组中的 UIView 是否完全重叠,然后调整位置
Determining if UIView in array of UIView's overlap with each other at all, and then adjust position
我在下面有一个循环,它应该检测 UIView
数组中的视图是否完全相互重叠。如果他们这样做,则调整他们的 center
值。
每个视图都是 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
}
}
}
}
...
}
下面是生成随机 CGPoint
并设置为视图中心的方法:
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
}
下面是确定两个UIView
之间距离的方法。
func distance(_ a: CGPoint, _ b: CGPoint) -> CGFloat {
let xDist = a.x - b.x
let yDist = a.y - b.y
return CGFloat(hypot(xDist, yDist))
}
但是,我仍然偶尔会遇到两个视图相互重叠的情况(请参阅下面的红色圆圈部分):
编辑 这是将圆圈添加到视图的代码:
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()
}
我想你应该可以这样做:
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.
}
请注意,这不会处理各种边缘情况,例如将相同的圆相互比较,但如果它们重叠,这应该会简化理解。
根据我上面关于将比较距离的逻辑移动到随机点的创建的评论,这里有一个快速选项:
这可以清理,但我不想完全重写它并尽可能多地使用你的代码。
在 generateCirles
函数中,我只更改了 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()
}
在 getRandomPoint
中,我添加了一个检查,以根据您现有的距离逻辑查看新点是否是有效点:
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
}
并且我从您发布的 drawCircles
中删除了您的所有代码。
这是 300 个圆圈的样子:(我使用视图框架作为 circlesView 框架,所以这就是为什么圆圈与屏幕边界重叠)这对你来说应该不是问题,因为我假设您的 circlesView 框架设置得更小。
我在下面有一个循环,它应该检测 UIView
数组中的视图是否完全相互重叠。如果他们这样做,则调整他们的 center
值。
每个视图都是 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
}
}
}
}
...
}
下面是生成随机 CGPoint
并设置为视图中心的方法:
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
}
下面是确定两个UIView
之间距离的方法。
func distance(_ a: CGPoint, _ b: CGPoint) -> CGFloat {
let xDist = a.x - b.x
let yDist = a.y - b.y
return CGFloat(hypot(xDist, yDist))
}
但是,我仍然偶尔会遇到两个视图相互重叠的情况(请参阅下面的红色圆圈部分):
编辑 这是将圆圈添加到视图的代码:
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()
}
我想你应该可以这样做:
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.
}
请注意,这不会处理各种边缘情况,例如将相同的圆相互比较,但如果它们重叠,这应该会简化理解。
根据我上面关于将比较距离的逻辑移动到随机点的创建的评论,这里有一个快速选项: 这可以清理,但我不想完全重写它并尽可能多地使用你的代码。
在 generateCirles
函数中,我只更改了 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()
}
在 getRandomPoint
中,我添加了一个检查,以根据您现有的距离逻辑查看新点是否是有效点:
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
}
并且我从您发布的 drawCircles
中删除了您的所有代码。
这是 300 个圆圈的样子:(我使用视图框架作为 circlesView 框架,所以这就是为什么圆圈与屏幕边界重叠)这对你来说应该不是问题,因为我假设您的 circlesView 框架设置得更小。