+++ /dev/null
-#include "geometry.h"
-
-#include <math.h>
-#include "misc.h"
-
-#include <QString>
-
-#include <iostream>
-using namespace std;
-
-
-QRectF addBBox(QRectF r1, QRectF r2)
-{
- // Find smallest QRectF containing given rectangles
-
- QRectF n;
- // Set left border
- if (r1.left() <= r2.left() )
- n.setLeft(r1.left() );
- else
- n.setLeft(r2.left() );
-
- // Set top border
- if (r1.top() <= r2.top() )
- n.setTop(r1.top() );
- else
- n.setTop(r2.top() );
-
- // Set right border
- if (r1.right() <= r2.right() )
- n.setRight(r2.right() );
- else
- n.setRight(r1.right() );
-
- // Set bottom
- if (r1.bottom() <= r2.bottom() )
- n.setBottom(r2.bottom() );
- else
- n.setBottom(r1.bottom() );
- return n;
-}
-
-QSize addBBoxSize (QSize s1, QSize s2)
-{
- // Find the minimimum smallest QSize which could include 2 given sizes
-
- QSize s=s1;
- if (s1.width() <= s2.width() )
- s.setWidth (s2.width() );
- if (s1.height() <= s2.height() )
- s.setHeight(s2.height() );
- return s;
-}
-
-bool isInBox(const QPointF &p, const QRectF &box)
-{
- if (p.x() >= box.left() && p.x() <= box.right()
- && p.y() <= box.bottom() && p.y() >= box.top() )
- return true;
- return false;
-}
-
-qreal Geometry::distance (const QPointF &p, const QPointF &q)
-{
- return sqrt (p.x()*q.x() + p.y()*q.y());
-}
-
-Vector::Vector ():QPointF ()
-{
-}
-
-Vector::Vector (const QPointF &p):QPointF (p)
-{
-}
-
-Vector::Vector (qreal x, qreal y):QPointF (x,y)
-{
-}
-
-Vector::~Vector ()
-{
-}
-
-//! Check if length is 0
-bool Vector::isNull()
-{
- if (x()==0 && y()==0)
- return true;
- return false;
-}
-
-//! Normalize vector
-void Vector::normalize ()
-{
- if (isNull() ) return;
- qreal l=sqrt ( x()*x() + y()*y() );
- setX (x()/l);
- setY (y()/l);
-}
-
-//! Dot product of two vectors
-qreal Vector::dotProduct (const QPointF &b)
-{
- return x()*b.x() + y()*b.y();
-}
-
-
-void Vector::scale (const qreal &f)
-{
- setX (x()*f);
- setY (y()*f);
-}
-
-void Vector::invert ()
-{
- setX (-x());
- setY (-y());
-}
-
-QPointF Vector::toQPointF ()
-{
- return QPointF (x(),y());
-}
-
-/*! Calculate the projection of a polygon on an axis
- and returns it as a [min, max] interval */
-ConvexPolygon::ConvexPolygon ()
-{
-}
-
-ConvexPolygon::ConvexPolygon (QPolygonF p):QPolygonF (p)
-{
-}
-
-ConvexPolygon::~ConvexPolygon ()
-{
-}
-
-void ConvexPolygon::calcCentroid()
-{
- // Calculate area and centroid
- // http://en.wikipedia.org/wiki/Centroid
- qreal cx,cy,p;
- cx=cy=0;
- _area=0;
-
- append (at(0));
- for (int i=0;i<size()-1;i++)
- {
- p=at(i).x() * at(i+1).y() - at(i+1).x() * at(i).y();
- _area+=p;
- cx+=(at(i).x()+at(i+1).x()) * p;
- cy+=(at(i).y()+at(i+1).y()) * p;
- }
- pop_back();
- // area is negative if vertices ordered counterclockwise
- // (in mirrored graphicsview!)
- _area=_area/2;
- p=_area*6;
- _centroid.setX (cx/p);
- _centroid.setY (cy/p);
-}
-
-QPointF ConvexPolygon::centroid() const
-{
- return _centroid;
-}
-
-qreal ConvexPolygon::weight() const
-{
- return _area;
-}
-
-std::string ConvexPolygon::toStdString()
-{
- QString s ("(");
- for (int i=0;i<size();++i)
- {
- s+=QString("(%1,%2)").arg(at(i).x()).arg(at(i).y());
- if (i<size()-1) s+=",";
- }
- s+=")";
- return s.toStdString();
-}
-
-Vector ConvexPolygon::at(const int &i) const
-{
- return Vector (QPolygonF::at(i).x(),QPolygonF::at(i).y());
-}
-
-void ConvexPolygon::translate ( const Vector & offset )
-{ translate (offset.x(),offset.y());}
-
-void ConvexPolygon::translate ( qreal dx, qreal dy )
-{
- QPolygonF::translate (dx,dy);
- _centroid=_centroid+QPointF (dx,dy);
-}
-
-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<<")";
- }
-}
-
-// Calculate the signed distance between [minA, maxA] and [minB, maxB]
-// The distance will be negative if the intervals overlap
-
-qreal intervalDistance(qreal minA, qreal maxA, qreal minB, qreal maxB) {
- if (minA < minB) {
- return minB - maxA;
- } else {
- return minA - maxB;
- }
-}
-
-/*!
- Check if polygon A is going to collide with polygon B.
- The last parameter is the *relative* velocity
- of the polygons (i.e. velocityA - velocityB)
-*/
-
-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;
-}
-
-/* The function can be used this way:
- QPointF polygonATranslation = new QPointF();
-*/
-
-
-/*
-PolygonCollisionResult r = PolygonCollision(polygonA, polygonB, velocity);
-
-if (r.WillIntersect)
- // Move the polygon by its velocity, then move
- // the polygons appart using the Minimum Translation Vector
- polygonATranslation = velocity + r.minTranslation;
-else
- // Just move the polygon by its velocity
- polygonATranslation = velocity;
-
-polygonA.Offset(polygonATranslation);
-
-*/
-
-