# HG changeset patch
# User insilmaril
# Date 1252412139 0
# Node ID 7d67be709091158d00c2f68dc5863892602d991a
# Parent  f1006de05c5453d4d6706c498ca17f6cb38f6cb5
First results in moving colliding MapCenters apart

diff -r f1006de05c54 -r 7d67be709091 branchobj.cpp
--- a/branchobj.cpp	Mon Sep 07 15:36:57 2009 +0000
+++ b/branchobj.cpp	Tue Sep 08 12:15:39 2009 +0000
@@ -143,7 +143,9 @@
 	if (parObj->getTreeItem()->depth()==0)	
 	{	// new parent is a mapcenter
 
-		QPointF p= normalize ( QPointF (m.x() - o->getChildPos().x(),
+		//FIXME-2 rewrite to us new normalize QPointF p= normalize ( QPointF (m.x() - o->getChildPos().x(),
+		//								  m.y() - o->getChildPos().y() ));
+		QPointF p= ( QPointF (m.x() - o->getChildPos().x(),
 									  m.y() - o->getChildPos().y() ));
 		if (p.x()<0) p.setX( p.x()-bbox.width() );
 		move2RelPos (p);
diff -r f1006de05c54 -r 7d67be709091 branchobj.h
--- a/branchobj.h	Mon Sep 07 15:36:57 2009 +0000
+++ b/branchobj.h	Tue Sep 08 12:15:39 2009 +0000
@@ -6,7 +6,6 @@
 #include "ornamentedobj.h"
 #include "xlinkobj.h"
 
-
 bool isAbove(BranchObj*,BranchObj*);
 
 /*! \brief A branch visible in the map */
diff -r f1006de05c54 -r 7d67be709091 geometry.cpp
--- a/geometry.cpp	Mon Sep 07 15:36:57 2009 +0000
+++ b/geometry.cpp	Tue Sep 08 12:15:39 2009 +0000
@@ -3,6 +3,8 @@
 #include <math.h>
 #include "misc.h"
 
+#include <QString>
+
 #include <iostream>
 using namespace std;
 
@@ -46,6 +48,48 @@
     return false;	
 }
 
+Vector::Vector ():QPointF ()
+{
+}
+
+Vector::Vector (const QPointF &p):QPointF (p)
+{
+}
+
+Vector::Vector (qreal x, qreal y):QPointF (x,y)
+{
+}
+
+//! Normalize vector
+void Vector::normalize ()
+{
+	if (x()==0 && y()==0) 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());
+}
+
+/*! Calculate the projection of a polygon on an axis
+    and returns it as a [min, max] interval  */
 ConvexPolygon::ConvexPolygon ()
 {
 }
@@ -89,45 +133,43 @@
 	return _area;
 }
 
-//! Normalize vector
-QPointF normalize (const QPointF &p)
+std::string ConvexPolygon::toStdString()
 {
-	if (p==QPointF(0,0)) return p;
-	qreal l=sqrt ( p.x()*p.x() + p.y()*p.y() );
-	return QPointF (p.x()/l,p.y()/l);
+	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();
 }
 
-//! Dot product of two vectors
-qreal dotProduct (const QPointF &a, const QPointF &b)
+Vector ConvexPolygon::at(const int &i) const
 {
-	return a.x()*b.x() + a.y()*b.y();
+	return Vector (QPolygonF::at(i).x(),QPolygonF::at(i).y());
 }
 
+void ConvexPolygon::translate ( const Vector & offset )
+{ translate (offset.x(),offset.y());}
 
-QPointF scale (const QPointF &v,const qreal &f)
+void ConvexPolygon::translate ( qreal dx, qreal dy )
 {
-	return QPointF (v.x()*f,v.y()*f);
+	QPolygonF::translate (dx,dy);
+	_centroid=_centroid+QPointF (dx,dy);
 }
 
-QPointF invert (const QPointF &v)
-{
-	return QPointF (-v.x(),-v.y());
-}
-
-/*! Calculate the projection of a polygon on an axis
-    and returns it as a [min, max] interval  */
-
-void projectPolygon(QPointF axis, QPolygonF polygon, qreal &min, qreal &max) 
+void projectPolygon(Vector axis, ConvexPolygon polygon, qreal &min, qreal &max) 
 {
     // To project a point on an axis use the dot product
 
 	//cout << "Projecting on "<< axis<<endl;
-    qreal d = dotProduct(axis,polygon.at(0));
+    qreal d = axis.dotProduct(polygon.at(0));
     min = d;
     max = d;
     for (int i = 0; i < polygon.size(); i++) 
 	{
-        d= dotProduct (polygon.at(i),axis);
+        d= polygon.at(i).dotProduct (axis);
         if (d < min) 
             min = d;
         else 
@@ -153,8 +195,8 @@
  of the polygons (i.e. velocityA - velocityB)
 */
 
-PolygonCollisionResult polygonCollision(QPolygonF polygonA, 
-                              QPolygonF polygonB, QPointF velocity) 
+PolygonCollisionResult polygonCollision(ConvexPolygon polygonA, 
+                              ConvexPolygon polygonB, Vector velocity) 
 {
     PolygonCollisionResult result;
     result.intersect = true;
@@ -207,8 +249,8 @@
 
         // Find the axis perpendicular to the current edge
 
-        QPointF axis (-edge.y(), edge.x());
-        axis=normalize(axis);
+        Vector axis (-edge.y(), edge.x());
+        axis.normalize();
 
         // Find the projection of the polygon on the current axis
 
@@ -226,7 +268,7 @@
 
         // Project the velocity on the current axis
 
-        qreal velocityProjection = dotProduct(axis,velocity);
+        qreal velocityProjection = axis.dotProduct(velocity);
 
         // Get the projection of polygon A during the movement
 
diff -r f1006de05c54 -r 7d67be709091 geometry.h
--- a/geometry.h	Mon Sep 07 15:36:57 2009 +0000
+++ b/geometry.h	Tue Sep 08 12:15:39 2009 +0000
@@ -6,6 +6,23 @@
 QRectF addBBox(QRectF r1, QRectF r2);
 bool isInBox(const QPointF &p, const QRectF &box);
 
+
+class Vector:public QPointF
+{
+public:
+	Vector ();
+	Vector (const QPointF &p);
+	Vector (qreal x, qreal y);
+
+	friend inline bool operator==(const Vector &v1, const Vector &v2 )
+	{ return v1.x()==v2.x() && v1.y()==v2.y(); }
+
+	virtual void normalize ();
+	virtual qreal dotProduct (const QPointF &b);
+	virtual void scale  (const qreal &f);
+	virtual void invert ();
+};
+
 class ConvexPolygon:public QPolygonF
 {
 public:
@@ -14,19 +31,15 @@
 	void calcCentroid() ;
 	QPointF centroid() const;
 	qreal weight() const;
+	std::string toStdString ();
+	Vector at (const int &i) const ; 
+	virtual void translate ( const Vector &offset );
+	virtual void translate ( qreal dx, qreal dy );
 private:
-	QPointF _centroid;
+	Vector _centroid;
 	qreal _area;
 };
 
-QPointF normalize (const QPointF &p);
-
-
-qreal dotProduct (const QPointF &a, const QPointF &b);
-
-QPointF scale  (const QPointF &v,const qreal &f);
-QPointF invert (const QPointF &v);
-
 class PolygonCollisionResult {
 public:
     // Are the polygons going to intersect forward in time?
@@ -40,10 +53,10 @@
 };
 
 
-void projectPolygon(QPointF axis, QPolygonF polygon, qreal &min, qreal &max) ;
+void projectPolygon(Vector axis, ConvexPolygon polygon, qreal &min, qreal &max) ;
 
 qreal intervalDistance(qreal minA, qreal maxA, qreal minB, qreal maxB);
-PolygonCollisionResult polygonCollision(QPolygonF polygonA, 
-                              QPolygonF polygonB, QPointF velocity);
+PolygonCollisionResult polygonCollision(ConvexPolygon polygonA, 
+                              ConvexPolygon polygonB, Vector velocity);
 
 #endif
\ No newline at end of file
diff -r f1006de05c54 -r 7d67be709091 mainwindow.cpp
--- a/mainwindow.cpp	Mon Sep 07 15:36:57 2009 +0000
+++ b/mainwindow.cpp	Tue Sep 08 12:15:39 2009 +0000
@@ -3595,7 +3595,7 @@
 void Main::testFunction2()
 {
 	if (!currentMapEditor()) return;
-	currentMapEditor()->setFocus();
+	currentMapEditor()->testFunction2();
 }
 
 void Main::testCommand()
diff -r f1006de05c54 -r 7d67be709091 mapeditor.cpp
--- a/mapeditor.cpp	Mon Sep 07 15:36:57 2009 +0000
+++ b/mapeditor.cpp	Tue Sep 08 12:15:39 2009 +0000
@@ -7,6 +7,7 @@
 #include <QObject>
 
 #include "branchitem.h"
+#include "geometry.h"
 #include "mainwindow.h"
 #include "misc.h"
 #include "warningdialog.h"
@@ -545,10 +546,6 @@
 	}	
 	cout <<"  hidemode="<<hidemode<<endl;
 	*/
-}
-	
-void MapEditor::testFunction2()
-{
 
 /*
 	// Toggle hidemode
@@ -557,6 +554,73 @@
 	else	
 		setHideTmpMode (HideExport);
 */		
+
+}
+	
+void MapEditor::testFunction2()
+{
+	// Create list with all bounding polygons
+	QList <MapObj*> mapobjects;
+	QList <ConvexPolygon> polys; 
+	QList <Vector> vectors;
+	QList <Vector> orgpos;
+	BranchItem *bi;
+	BranchObj *bo;
+	TreeItem *ri=model->getRootItem();
+	for (int i=0;i<ri->branchCount();++i)
+	{
+		bi=ri->getBranchNum (i);
+		bo=(BranchObj*)bi->getLMO();
+		if (bo)
+		{
+			mapobjects.append (bo);
+			polys.append(bo->getBoundingPolygon());
+			polys[i].calcCentroid();
+			vectors.append (QPointF(0,0));
+			orgpos.append (polys[i].at(0));
+		}	
+	}
+
+	// Iterate moving bounding polygons until we have no more collisions
+	int collisions=1;
+	while (collisions>0)
+	{
+		collisions=0;
+		for (int i=0; i<polys.size()-1; ++i)
+		{
+			for (int j=i+1; j<polys.size();++j)
+			{
+				if (polygonCollision (polys.at(i),polys.at(j), QPointF(0,0)).intersect )
+				{
+					collisions++;
+					Vector v=polys.at(j).centroid()-polys.at(i).centroid();
+					// Move also away if centroids are identical
+					if (v.isNull()) 
+					{
+						v.setX (rand()%200 -100);
+						v.setY (rand()%200 -100);
+					}
+					v.normalize();
+					cout << "v="<<v<<endl;
+					v.scale (2);
+					vectors[j]=v;
+					vectors[i]=v;
+					vectors[i].invert();
+				} 
+			}
+		}
+		for (int i=0;i<vectors.size();i++)
+			polys[i].translate (vectors[i]);
+		//cout << "Collisions: "<<collisions<<endl;
+	}	
+
+	// Finally move the real objects and update 
+	for (int i=0;i<polys.size();i++)
+	{
+		Vector v=polys[i].at(0)-orgpos[i];
+		mapobjects[i]->moveBy(v.x(),v.y() );
+	}	
+	model->reposition();	
 }
 
 BranchItem* MapEditor::getBranchDirectAbove (BranchItem *bi)
@@ -1050,8 +1114,8 @@
 			if ( e->modifiers()==Qt::ShiftModifier && dsti &&  dsti != seli->parent()  )
 			{
 				// Also save the move which was done so far
-				QString pold=qpointfToString(movingObj_orgRelPos);
-				QString pnow=qpointfToString(fio->getRelPos());
+				QString pold=qpointFToString(movingObj_orgRelPos);
+				QString pnow=qpointFToString(fio->getRelPos());
 				model->saveState(
 					seli,
 					"moveRel "+pold,
@@ -1205,8 +1269,8 @@
 			if(fio)
 			{
 				// Moved FloatObj. Maybe we need to reposition
-				QString pold=qpointfToString(movingObj_orgRelPos);
-				QString pnow=qpointfToString(fio->getRelPos());
+				QString pold=qpointFToString(movingObj_orgRelPos);
+				QString pnow=qpointFToString(fio->getRelPos());
 				model->saveState(
 					seli,
 					"moveRel "+pold,
@@ -1225,8 +1289,8 @@
 		{	
             if (movingObj_orgPos != bi->getBranchObj()->getAbsPos())	// FIXME-3 check getBO here...
             {
-                QString pold=qpointfToString(movingObj_orgPos);
-                QString pnow=qpointfToString(bi->getBranchObj()->getAbsPos());		// FIXME-3 check getBO here...
+                QString pold=qpointFToString(movingObj_orgPos);
+                QString pnow=qpointFToString(bi->getBranchObj()->getAbsPos());		// FIXME-3 check getBO here...
 
                 model->saveState(
                     bi,
@@ -1311,9 +1375,9 @@
                     QPointF rp(lmosel->getRelPos());
                     if (rp != movingObj_orgRelPos)
                     {
-                        QString ps=qpointfToString(rp);
+                        QString ps=qpointFToString(rp);
                         model->saveState(
-                            model->getSelectString(lmosel), "moveRel "+qpointfToString(movingObj_orgRelPos), 
+                            model->getSelectString(lmosel), "moveRel "+qpointFToString(movingObj_orgRelPos), 
                             preSelStr, "moveRel "+ps, 
                             QString("Move %1 to relative position %2").arg(model->getObjectName(lmosel)).arg(ps));
                     }
diff -r f1006de05c54 -r 7d67be709091 mapobj.cpp
--- a/mapobj.cpp	Mon Sep 07 15:36:57 2009 +0000
+++ b/mapobj.cpp	Tue Sep 08 12:15:39 2009 +0000
@@ -90,7 +90,7 @@
 
 QString MapObj::getPos()
 {
-	return qpointfToString(absPos);
+	return qpointFToString(absPos);
 }
 
 void MapObj::move (double x, double y) 
@@ -120,6 +120,13 @@
     return bbox;
 }
 
+ConvexPolygon MapObj::getBoundingPolygon()
+{
+	QPolygonF p;
+	p<<bbox.topLeft()<<bbox.topRight()<<bbox.bottomRight()<<bbox.bottomLeft();
+	return p;
+}
+
 QRectF MapObj::getClickBox()
 {
     return clickBox;
diff -r f1006de05c54 -r 7d67be709091 mapobj.h
--- a/mapobj.h	Mon Sep 07 15:36:57 2009 +0000
+++ b/mapobj.h	Tue Sep 08 12:15:39 2009 +0000
@@ -16,6 +16,7 @@
 #define Z_TEXT     100
 #define Z_LINEEDIT 110
 
+class ConvexPolygon;
 
 class TreeItem;
 
@@ -40,26 +41,27 @@
 	virtual qreal width();
 	virtual qreal height();
 	virtual QPointF getAbsPos();
-	virtual QString getPos();					// Return position as string (x,y)
-    virtual void move (double x,double y);      // move to absolute Position
+	virtual QString getPos();					//! Return position as string (x,y)
+    virtual void move (double x,double y);      //! move to absolute Position
     virtual void move (QPointF p);
-    virtual void moveBy (double x,double y);    // move to relative Position
-    virtual QRectF getBBox();					// returns bounding box
-    virtual QRectF getClickBox();				// returns box to click
+    virtual void moveBy (double x,double y);    //! move to relative Position
+    virtual QRectF getBBox();					//! returns bounding box
+    virtual ConvexPolygon getBoundingPolygon();	//! return bounding convex polygon
+    virtual QRectF getClickBox();				//! returns box to click
 	virtual bool isInClickBox (const QPointF &p);	//! Checks if p is in clickBox
-    virtual QSizeF getSize();					// returns size of bounding box
+    virtual QSizeF getSize();					//! returns size of bounding box
     virtual bool isVisibleObj();
     virtual void setVisibility(bool);
     virtual void positionBBox()=0;       
 	virtual void calcBBoxSize()=0;
 protected:  
     QGraphicsScene* scene;
-    QRectF bbox;									// bounding box of MO itself
-	QRectF clickBox;								// area where mouseclicks are found
-    QPointF absPos;							    // Position on canvas
+    QRectF bbox;					// bounding box of MO itself
+	QRectF clickBox;				// area where mouseclicks are found
+    QPointF absPos;				    // Position on canvas
     bool visible;
 
-	TreeItem *treeItem;				// Crossrefence to treemodel
+	TreeItem *treeItem;				//! Crossrefence to treemodel
 
 };
 
diff -r f1006de05c54 -r 7d67be709091 misc.cpp
--- a/misc.cpp	Mon Sep 07 15:36:57 2009 +0000
+++ b/misc.cpp	Tue Sep 08 12:15:39 2009 +0000
@@ -1,20 +1,21 @@
 #include <math.h>
 
 #include <qregexp.h>
-#include <qpoint.h>
+//#include <qpoint.h>
 #include <stdlib.h>
 
 #include "misc.h"
 
+#include "geometry.h"
+
 QString qpointToString (const QPoint &p)
-{
-	return "(" + QString("%1").arg(p.x()) +","+ QString ("%1").arg (p.y()) +")";
-}
+{ return "(" + QString("%1").arg(p.x()) +","+ QString ("%1").arg (p.y()) +")"; }
 
-QString qpointfToString (const QPointF &p)
-{
-	return "(" + QString("%1").arg(p.x()) +","+ QString ("%1").arg (p.y()) +")";
-}
+QString qpointFToString (const QPointF &p)
+{ return "(" + QString("%1").arg(p.x()) +","+ QString ("%1").arg (p.y()) +")"; }
+
+QString VectorToString (const Vector &p)
+{ return "(" + QString("%1").arg(p.x()) +","+ QString ("%1").arg (p.y()) +")"; }
 
 ostream &operator<< (ostream &stream, QPoint const &p)
 { 
@@ -28,6 +29,12 @@
 	return stream;
 }
 
+ostream &operator<< (ostream &stream, Vector const &p)
+{ 
+	stream << "("<<p.x()<<","<<p.y()<<")";
+	return stream;
+}
+
 qreal getAngle(const QPointF &p)
 {	
 	// Calculate angle of vector to y-axis
diff -r f1006de05c54 -r 7d67be709091 misc.h
--- a/misc.h	Mon Sep 07 15:36:57 2009 +0000
+++ b/misc.h	Tue Sep 08 12:15:39 2009 +0000
@@ -1,18 +1,23 @@
 #ifndef MISC_H
 #define MISC_H
 
-#include <qpoint.h>
-#include <qdir.h>
 #include <iostream>
-
 using namespace std;
 
+class QString;
+class QPoint;
+class QPointF;
+class Vector;
 
 /////////////////////////////////////////////////////////////////////////////
 QString qpointToString (const QPoint &p);
-QString qpointfToString (const QPointF &p);
+QString qpointFToString (const QPointF &p);
+QString VectorToString (const Vector &p);
+
+
 extern ostream &operator<< (ostream &stream, QPoint const &p);
 extern ostream &operator<< (ostream &stream, QPointF const &p);
+extern ostream &operator<< (ostream &stream, Vector const &p);
 qreal getAngle(const QPointF &);
 qreal max (qreal,qreal);
 
diff -r f1006de05c54 -r 7d67be709091 version.h
--- a/version.h	Mon Sep 07 15:36:57 2009 +0000
+++ b/version.h	Tue Sep 08 12:15:39 2009 +0000
@@ -7,7 +7,7 @@
 #define __VYM_VERSION "1.13.0"
 //#define __VYM_CODENAME "Codename: RC-1"
 #define __VYM_CODENAME "Codename: development version, not for production!"
-#define __VYM_BUILD_DATE "2009-09-07"
+#define __VYM_BUILD_DATE "2009-09-08"
 
 
 bool checkVersion(const QString &);
diff -r f1006de05c54 -r 7d67be709091 vymmodel.cpp
--- a/vymmodel.cpp	Mon Sep 07 15:36:57 2009 +0000
+++ b/vymmodel.cpp	Tue Sep 08 12:15:39 2009 +0000
@@ -2341,15 +2341,13 @@
 				"delete ()",
 				QString("Delete %1").arg(getObjectName(ti))
 			);
+			unselect();
+			deleteItem (ti);
+			emitDataHasChanged (pi);
+			select (pi);
+			reposition();
+			emitShowSelection();
 		}
-		// FIXME-1 savestate missing for deletion of other types than above
-		unselect();
-		deleteItem (ti);
-		emitDataHasChanged (pi);
-		select (pi);
-		reposition();
-		emitShowSelection();
-		return;
 	}
 }
 
@@ -4028,6 +4026,7 @@
 
 	for (int i=0;i<rootItem->branchCount(); i++)
 		rootItem->getBranchObjNum(i)->reposition();	//	for positioning heading
+	emitSelectionChanged();	
 }
 
 /*
diff -r f1006de05c54 -r 7d67be709091 xml-vym.cpp
--- a/xml-vym.cpp	Mon Sep 07 15:36:57 2009 +0000
+++ b/xml-vym.cpp	Tue Sep 08 12:15:39 2009 +0000
@@ -145,7 +145,7 @@
 		{
 			// Treat the found mapcenter as a branch 
 			// in an existing map
-			BranchItem *bi=model->getSelectedBranch();	//FIXME-3 selection is no longer used here... //FIXME-2 really? we are adding to a map...
+			BranchItem *bi=model->getSelectedBranch();	//FIXME-2 selection is no longer used here... 
 			if (bi)
 			{
 				lastBranch=bi;
@@ -153,7 +153,7 @@
 				{
 					lastBranch=model->createBranch(lastBranch);
 				} //else
-					//lastBranch->clear(); //FIXME-1 clear not really defined!
+					//lastBranch->clear(); //FIXME-2 clear not really defined!
 			} else
 				// add mapCenter without parent
 				lastBranch=model->createMapCenter();