确定UIView数组中的UIView是否相互重叠,然后调整位置

问题描述

下面有一个循环,用于检测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))
}

但是,有时我仍然会遇到两个视图相互重叠的情况(请参见下面的红色圆圈部分):

enter image description here

编辑,这是将圆圈添加到视图的代码

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()
}

解决方法

根据我上面的评论,这是一个快速的选择,它涉及将用于比较距离的逻辑转换为随机点的创建: 可以清除此错误,但我不想完全重写它,而要使用尽可能多的代码。

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个圆的外观:(我使用视框作为circleView框,所以这就是为什么圆与屏幕边界重叠的原因)这对您来说应该不是问题,因为我认为您是circleView框架设置为较小。 enter image description here

,

我认为您应该可以执行以下操作:

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.
}

请注意,这不能处理各种边缘情况,例如将相同的圆彼此进行比较,但这应该简化对它们重叠的理解。