1

Here's the relevant piece of code:

QPointF GraphicsItem::handleCollisions(const QPointF& new_pos) const {
    auto collisions = collidingItems();
    auto rect = mapToParent(boundingRect().translated(new_pos - pos())).boundingRect();
    for(int k=0; k < collisions.count(); k++)
    {
        auto item = collisions[k];
        if (item->parentItem() == parentItem()) {
            auto rect1 = item->mapToParent(item->boundingRect()).boundingRect();
            rect1 = rect1.intersected(rect);
            auto v = rect1.center() - rect.center();
            if (v.x() >= 0) {
                if (v.y() >= 0) {
                    if (rect1.width() <= rect1.height())
                        item->setPos(item->pos() + QPointF(rect1.width(), 0) * 1.5);
                    else
                        item->setPos(item->pos() + QPointF(0, rect1.height()));
                }
                else {
                    if (rect1.width() <= rect1.height())
                        item->setPos(item->pos() + QPointF(rect1.width(), 0));
                    else
                        item->setPos(item->pos() + QPointF(0, -rect1.height()));
                }
            }
            else {
                if (v.y() >= 0) {
                    if (rect1.width() <= rect1.height())
                        item->setPos(item->pos() + QPointF(-rect1.width(), 0));
                    else
                        item->setPos(item->pos() + QPointF(0, rect1.height()));
                }
                else {
                    if (rect1.width() <= rect1.height())
                        item->setPos(item->pos() + QPointF(-rect1.width(), 0));
                    else
                        item->setPos(item->pos() + QPointF(0, -rect1.height()));
                }
            }
        }
    }
    return new_pos;     // return this position unchanged
}

Here's a video showing the result, which is very low quality IMHO.

YouTube Video

I'd like the result to be smooth: Ie. the pushed box moves at precisely the same velocity as the pushing box.

Thanks for your mathematical ingenuity. It will not go unpayed. I am making this app for you: a visual diagram chaser with the ability to create new logic rules visually. It has never been done.

What you saw in the video was a a C++ application I'm writing as a port of an earlier python prototype I showed you:

Previous post


Question for you: Is 10 dollars to much to ask per license on a kickstarter campaign? That would amount to 10,000 USD if I sold 1000 copies, and I'm sure I can snag at least that many of you, because this app will be the shits.

If you're interested in how I plan to implement the categorical logic, please ask. It is a way that hasn't been tried before AFAIK.

  • I think I can solve this with a collision list. First we move like we did in the code above, but successive moves within the same mouse move sequence (demarked by press/release of mouse) always move the items in the collision list by the same delta as the item being moved or maybe a component there of, until the mouse is released. The collision list gets populated with colliding items and updated each call to handleCollisions(). I think that might work. – Daniel Donnelly Sep 16 '18 at 05:42

1 Answers1

0

I've got a partial solution. The code simplifies (in Qt5) down to this simple snippet:

QPointF GraphicsItem::handleCollisions(const QPointF& new_pos) const {
    auto collisions = collidingItems();
    auto delta = new_pos - this->pos();
    auto parent = parentItem();

    for (int k=0; k < collisions.count(); k++) {
        auto item = collisions[k];
        if (item->parentItem() == parent) {
            // Without this check, the boxes stick together, kind of neat
            if (collidesWithPath(item->mapToItem(this, item->shape().translated(delta * 1.1))));
                item->setPos(item->pos() + delta);
        }
    }

    return new_pos;     // Return pos unchanged
}

Only problem is the boxes stick together now. They move perfectly in synchrony but they're stuck. So I put that check there, but it's not working. I'll post a solution to this when I find the bug.


The inner if condition should be:

    if (item->collidesWithPath(mapToItem(item, shape.translated(delta)))) {
        item->setPos(item->pos() + delta);
    }