An algorithm to space out overlapping rectangles?

后端 未结 6 1230
感情败类
感情败类 2020-11-28 18:31

This problem actually deals with roll-overs, I\'ll just generalized below as such:

I have a 2D view, and I have a number of rectangles within an area on the screen.

6条回答
  •  悲&欢浪女
    2020-11-28 18:58

    I really like b005t3r's implementation! It works in my test cases, however my rep is too low to leave a comment with the 2 suggested fixes.

    1. You should not be translating rooms by single resolution increments, you should translate by the velocity you just pain stakingly calculated! This makes the separation more organic as deeply intersected rooms separate more each iteration than not-so-deeply intersecting rooms.

    2. You should not assume velociites less than 0.5 means rooms are separate as you can get stuck in a case where you are never separated. Imagine 2 rooms intersect, but are unable to correct themselves because whenever either one attempts to correct the penetration they calculate the required velocity as < 0.5 so they iterate endlessly.

    Here is a Java solution (: Cheers!

    do {
        _separated = true;
    
        for (Room room : getRooms()) {
            // reset for iteration
            Vector2 velocity = new Vector2();
            Vector2 center = room.createCenter();
    
            for (Room other_room : getRooms()) {
                if (room == other_room)
                    continue;
    
                if (!room.createRectangle().overlaps(other_room.createRectangle()))
                    continue;
    
                Vector2 other_center = other_room.createCenter();
                Vector2 diff = new Vector2(center.x - other_center.x, center.y - other_center.y);
                float diff_len2 = diff.len2();
    
                if (diff_len2 > 0f) {
                    final float repelDecayCoefficient = 1.0f;
                    float scale = repelDecayCoefficient / diff_len2;
                    diff.nor();
                    diff.scl(scale);
    
                    velocity.add(diff);
                }
            }
    
            if (velocity.len2() > 0f) {
                _separated = false;
    
                velocity.nor().scl(delta * 20f);
    
                room.getPosition().add(velocity);
            }
        }
    } while (!_separated);
    

提交回复
热议问题