void projectPolygon(Vector axis, ConvexPolygon polygon, qreal &min, qreal &max) { // To project a point on an axis use the dot product //qDebug() << "Projecting on "<< axis; qreal d = axis.dotProduct(polygon.at(0)); min = d; max = d; for (int i = 0; i < polygon.size(); i++) { d= polygon.at(i).dotProduct (axis); if (d < min) min = d; else if (d> max) max = d; // qDebug() << "p="<<polygon.at(i)<<" d="<<d<<" (min, max)=("<<min<<","<<max<<")"; } }
PolygonCollisionResult polygonCollision(ConvexPolygon polygonA, ConvexPolygon polygonB, Vector velocity) { PolygonCollisionResult result; result.intersect = true; result.willIntersect = true; int edgeCountA = polygonA.size(); int edgeCountB = polygonB.size(); qreal minIntervalDistance = 1000000000; QPointF translationAxis; QPointF edge; /* qDebug() << "A: "; for (int k=0; k<edgeCountA;k++) qDebug() <<polygonA.at(k); qDebug() << "B: "; for (int k=0; k<edgeCountB;k++) qDebug() <<polygonB.at(k); qDebug() ; */ // Loop through all the edges of both polygons for (int i=0;i<edgeCountA + edgeCountB;i++) { if (i< edgeCountA) { // Loop through polygon A if (i<edgeCountA-1) edge = QPointF ( polygonA.at(i+1).x()-polygonA.at(i).x(), polygonA.at(i+1).y()-polygonA.at(i).y()); else edge = QPointF ( polygonA.at(0).x()-polygonA.at(i).x(), polygonA.at(0).y()-polygonA.at(i).y()); } else { // Loop through polygon B if (i < edgeCountA +edgeCountB -1 ) edge = QPointF ( polygonB.at(i-edgeCountA+1).x() - polygonB.at(i-edgeCountA).x(), polygonB.at(i-edgeCountA+1).y() - polygonB.at(i-edgeCountA).y()); else edge = QPointF ( polygonB.at(0).x() - polygonB.at(i-edgeCountA).x(), polygonB.at(0).y() - polygonB.at(i-edgeCountA).y()); } // ===== 1. Find if the polygons are currently intersecting ===== // Find the axis perpendicular to the current edge Vector axis (-edge.y(), edge.x()); axis.normalize(); // Find the projection of the polygon on the current axis qreal minA = 0; qreal minB = 0; qreal maxA = 0; qreal maxB = 0; projectPolygon(axis, polygonA, minA, maxA); projectPolygon(axis, polygonB, minB, maxB); // Check if the polygon projections are currentlty intersecting qreal d = intervalDistance(minA, maxA, minB, maxB); if (d > 0) result.intersect = false; // ===== 2. Now find if the polygons *will* intersect ===== // Project the velocity on the current axis qreal velocityProjection = axis.dotProduct(velocity); // Get the projection of polygon A during the movement if (velocityProjection < 0) minA += velocityProjection; else maxA += velocityProjection; // Do the same test as above for the new projection // d = intervalDistance(minA, maxA, minB, maxB); //if (d > 0) result.willIntersect = false; /* qDebug() <<" "; qDebug() << "edge="<<edge<<" "; qDebug() <<"axis="<<axis<<" "; qDebug() <<"dA=("<<minA<<","<<maxA<<") dB=("<<minB<<","<<maxB<<")"; qDebug() <<" d="<<d<<" "; //qDebug() <<"minD="<<minIntervalDistance<<" "; qDebug() <<"int="<<result.intersect<<" "; //qDebug() <<"wint="<<result.willIntersect<<" "; //qDebug() <<"velProj="<<velocityProjection<<" "; qDebug() ; */ if (result.intersect )// || result.willIntersect) { // Check if the current interval distance is the minimum one. If so // store the interval distance and the current distance. This will // be used to calculate the minimum translation vector if (d<0) d=-d; if (d < minIntervalDistance) { minIntervalDistance = d; //translationAxis = axis; //qDebug() << "tAxix="<<translationAxis; //QPointF t = polygonA.Center - polygonB.Center; //QPointF t = polygonA.at(0) - polygonB.at(0); //if (dotProduct(t,translationAxis) < 0) // translationAxis = -translationAxis; } } } // The minimum translation vector // can be used to push the polygons appart. if (result.willIntersect) result.minTranslation = translationAxis * minIntervalDistance; return result; }