Files
lsim/src/graphicsellipseitem.cpp
2008-12-16 21:59:25 +00:00

338 lines
11 KiB
C++

/***************************************************************************
* Copyright (C) 2008 by Peter Dahlberg *
* pdahlberg@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "graphicsellipseitem.h"
#include <QDrag>
#include <QGraphicsSceneMouseEvent>
#include <QMimeData>
#include <QPainterPath>
#include <QGraphicsPathItem>
#include <QDebug>
#include "simulscene.h"
#include "probechargewidget.h"
#include <cmath>
#include "constants.h"
#include <iostream>
#include <climits>
GraphicsEllipseItem::GraphicsEllipseItem() {
//setFlag(ItemIsMovable);
//setFlag(ItemIsSelectable);
setFlag(ItemIsFocusable);
//setCacheMode(QGraphicsItem::DeviceCoordinateCache);
//startTimer(100);
myProbeChargeWidget = new ProbeChargeWidget(0,0,this);
currProbePath = new QList<QPointF>;
speedListX = new QList<double>;
speedListY = new QList<double>;
elapsedTimeList= new QList<double>;
setupVars();
}
void GraphicsEllipseItem::setupVars () {
setMasse(9.10938188e-31);
setCharge(-1.6e-19);
setStartSpeedX(0);
setStartSpeedY(0);
setPos(0,0);
setAdaptiveStepLength(0.01);
setAdaptiveStepControl(true);
}
void GraphicsEllipseItem::resetProbe() {
setupVars();
}
void GraphicsEllipseItem::timerEvent ( QTimerEvent * event ) {
static double vx;
vx++;
//moveBy(vx/20.0,vx/20.0*vx/20.0);
}
GraphicsEllipseItem::~GraphicsEllipseItem() {
}
void GraphicsEllipseItem::mousePressEvent ( QGraphicsSceneMouseEvent *event ) {
//QGraphicsEllipseItem::mousePressEvent(event);
}
void GraphicsEllipseItem::handleSceneChange(const QList<QRectF> & /*region*/) {
if (myScenePos != scenePos()) {
myScenePos = scenePos();
emit ScenePosChanged(myScenePos);
emit ScenePosXChanged(myScenePos.x());
emit ScenePosYChanged(myScenePos.y());
}
}
/*!
\fn GraphicsEllipseItem::calculateProbePath()
*/
void GraphicsEllipseItem::calculateProbePath(QPointF startPoint) {
double startSpeedX = getStartSpeedX();
double startSpeedY = getStartSpeedY();
SimulScene* myScene = dynamic_cast<SimulScene*>(scene());
//wenn noch zu keiner scene gehoerend abbruch
if (myScene == 0) return;
//parameter der scene in lokale variablen uebernehmen
double timePerStep = myScene->getTimePerStep();
int steps = myScene->getSteps();
double meterPerPx = myScene->getMeterPerPx();
//listen leeren
currProbePath->clear();
speedListX->clear();
speedListY->clear();
elapsedTimeList->clear();
//startwerte in die listen setzen
currProbePath->append(startPoint);
speedListX->append(startSpeedX);
speedListY->append(startSpeedY);
elapsedTimeList->append(0);
//startpunkt in den Pfad setzen
flightPath = QPainterPath(startPoint);
for(int i = 1; i< steps;++i) {
//Geschwindigkeit (gesamt)
double combinedSpeed = sqrt( speedListX->at(i-1)*speedListX->at(i-1) + speedListY->at(i-1)*speedListY->at(i-1) );
double myMasse = getMasse(combinedSpeed);
//qDebug()<< myMasse;
double powerX = myScene->getPowerAt(currProbePath->at(i-1), charge, speedListX->at(i-1),speedListY->at(i-1), 'x');
double powerY = myScene->getPowerAt(currProbePath->at(i-1), charge, speedListX->at(i-1),speedListY->at(i-1), 'y');
//automatische Zeitschrittanpassung 0.008
if (isAdaptiveStepControlEnabled()&&combinedSpeed != 0) timePerStep = getAdaptiveStepLength()/(combinedSpeed/meterPerPx);
//if (timePerStep < (1/10.0 * myScene->getTimePerStep())) timePerStep = 1/10.0 * myScene->getTimePerStep();
//if (timePerStep > (19.0/10.0 * myScene->getTimePerStep())) timePerStep = 19.0/10.0 * myScene->getTimePerStep();
double combinedPower = sqrt(powerX*powerX+powerY*powerY);
if (isAdaptiveStepControlEnabled() && combinedPower !=0) {
timePerStep = fabs((-combinedSpeed + sqrt(combinedSpeed*combinedSpeed + 2*(combinedPower/myMasse)*getAdaptiveStepLength()*meterPerPx)) / (combinedPower/myMasse));
}
//qDebug()<<timePerStep;
double deltaSpeedX = (powerX/myMasse * timePerStep);
double deltaSpeedY = (powerY/myMasse * timePerStep);
double newspeedX = speedListX->at(i-1) + deltaSpeedX;
double newspeedY = speedListY->at(i-1) + deltaSpeedY;
double deltaDistX = (newspeedX * timePerStep);
double deltaDistY = (newspeedY * timePerStep);
//qDebug() << deltaDistY;
//if (i >= 4) {
// double dvx = (-9*speedListX->at(i-4)+37*speedListX->at(i-3)-59*speedListX->at(i-2)+55*speedListX->at(i-1))/24.0;
// double dvy = (-9*speedListY->at(i-4)+37*speedListY->at(i-3)-59*speedListY->at(i-2)+55*speedListY->at(i-1))/24.0;
//double dvx = (xp) / timePerStep ;
//double dvy = (yp) / timePerStep ;
// deltaDistX = timePerStep/24.0 *(speedListX->at(i-3)- 5*speedListX->at(i-2)+19*speedListX->at(i-1)+9*dvx);
// deltaDistY = timePerStep/24.0 *(speedListY->at(i-3)- 5*speedListY->at(i-2)+19*speedListY->at(i-1)+9*dvy);
//qDebug()<< deltaDistX<< " "<< deltaDistY;
//}
// double k1x = deltaDistX;
// double k1y = deltaDistY;
// QPointF k2point = QPointF(currProbePath->at(i-1).x() * meterPerPx + k1x/2.0,currProbePath->at(i-1).y()* meterPerPx + k1y/2.0);
// double k2x = myScene->getPowerAt( k2point , charge, k1x/timePerStep,k1y/timePerStep, 'x') /myMasse * timePerStep/2.0 * timePerStep;
// double k2y = myScene->getPowerAt( k2point , charge, k1x/timePerStep,k1y/timePerStep, 'y') /myMasse * timePerStep/2.0 * timePerStep;
// QPointF k3point = QPointF(currProbePath->at(i-1).x()* meterPerPx + k2x/2.0,currProbePath->at(i-1).y()* meterPerPx + k2y/2.0);
// double k3x = myScene->getPowerAt( k3point , charge, k2x/timePerStep,k2y/timePerStep, 'x') /myMasse * timePerStep/2.0 * timePerStep;
// double k3y = myScene->getPowerAt( k3point , charge, k2x/timePerStep,k2y/timePerStep, 'y') /myMasse * timePerStep/2.0 * timePerStep;
// QPointF k4point = QPointF(currProbePath->at(i-1).x() + k3x,currProbePath->at(i-1).y() + k3y);
// double k4x = myScene->getPowerAt( k4point , charge, k3x/timePerStep,k3y/timePerStep, 'x') /myMasse * timePerStep * timePerStep;
// double k4y = myScene->getPowerAt( k4point , charge, k3x/timePerStep,k3y/timePerStep, 'y') /myMasse * timePerStep * timePerStep;
//
// deltaDistX = (k1x +2*k2x+2*k3x+k4x)/6.0;
// deltaDistY = (k1y +2*k2y+2*k3y+k4y)/6.0;
QPointF newPoint(currProbePath->at(i-1).x() + deltaDistX/meterPerPx ,currProbePath->at(i-1).y() + deltaDistY/meterPerPx);
//Scrollbar int Probleme vermeiden
if (newPoint.x() + 10 > INT_MAX || newPoint.x() - 10 < INT_MIN) break;
if (newPoint.y() + 10 > INT_MAX || newPoint.y() - 10 < INT_MIN) break;
if (myScene->stopsHere(currProbePath->at(i-1),newPoint)) break;
currProbePath->append(newPoint);
speedListX->append(newspeedX);
speedListY->append(newspeedY);
elapsedTimeList->append(elapsedTimeList->at(i-1) + timePerStep);
}
int path_entry_step = currProbePath->count()/5000.0; //jeder entry_step(te) step wird eingetragen
if (path_entry_step == 0) path_entry_step = 1;
for (int i = 1; i< currProbePath->count();++i) {
if (i%path_entry_step == 0 || i==currProbePath->count()) flightPath.lineTo(currProbePath->at(i));
}
qDebug()<< "Probe Path: " <<*currProbePath;
//qDebug()<< "speed x: "<<*speedListX;
//qDebug()<< "speed y: "<<*speedListY;
//qDebug()<<speedListY->at(12);
//qDebug()<<"power x: "<< (double)myScene->getPowerAt(QPointF(0,0), charge, 'x');
//qDebug()<<"power y: " << (double)myScene->getPowerAt(QPointF(0,0), charge, 'y');
//qDebug()<< getMasse(5e+20);
}
QList<double> *GraphicsEllipseItem::getElapsedTimeList() {
return elapsedTimeList;
}
double GraphicsEllipseItem::getMasse(double speed) {
//damit kein inf oder nan entsteht
if(speed > (SPEED_OF_LIGHT - 3e-8)) speed = SPEED_OF_LIGHT - 3e-8; //fuer v>=c nehme v (etwas)<c an
if(speed < SPEED_OF_LIGHT/10.0) return masse;
return masse / (sqrt(1- ( (speed/SPEED_OF_LIGHT)*(speed/SPEED_OF_LIGHT))));
}
void GraphicsEllipseItem::setMasse ( const double& theValue ) {
if (masse == theValue) return;
masse = theValue;
emit masseChanged(theValue);
}
double GraphicsEllipseItem::getCharge() const {
return charge;
}
void GraphicsEllipseItem::setCharge ( const double& theValue ) {
if (charge == theValue) return;
charge = theValue;
emit chargeChanged(theValue);
}
QWidget * GraphicsEllipseItem::getDockWidget() const
{
return myProbeChargeWidget;
}
QList<QPointF> * GraphicsEllipseItem::getCurrProbePath() {
return currProbePath;
}
double GraphicsEllipseItem::getStartSpeedX() const {
return startSpeedX;
}
void GraphicsEllipseItem::setStartSpeedX ( double theValue ) {
if (startSpeedX == theValue) return;
startSpeedX = theValue;
emit startSpeedXChanged(theValue);
}
double GraphicsEllipseItem::getStartSpeedY() const {
return startSpeedY;
}
void GraphicsEllipseItem::setStartSpeedY ( double theValue ) {
if (startSpeedY == theValue) return;
startSpeedY = theValue;
emit startSpeedYChanged(theValue);
}
/*!
\fn GraphicsEllipseItem::setScenePosY(double posY)
*/
void GraphicsEllipseItem::setScenePosY(double newPosY)
{
moveBy(0, newPosY - scenePos().y());
}
/*!
\fn GraphicsEllipseItem::setScenePosX(double posX)
*/
void GraphicsEllipseItem::setScenePosX(double newPosX)
{
moveBy(newPosX - scenePos().x(),0 );
}
QPainterPath GraphicsEllipseItem::getFlightPath() const {
return flightPath;
}
void GraphicsEllipseItem::setFlightPath ( const QPainterPath& theValue ) {
if (flightPath==theValue) return;
flightPath = theValue;
}
bool GraphicsEllipseItem::isAdaptiveStepControlEnabled() const {
return adaptiveStepControlEnabled;
}
void GraphicsEllipseItem::setAdaptiveStepControl ( bool theValue ) {
if (adaptiveStepControlEnabled == theValue) return;
adaptiveStepControlEnabled = theValue;
emit adaptiveStepControlChanged(theValue);
}
double GraphicsEllipseItem::getAdaptiveStepLength() const {
return adaptiveStepLength;
}
void GraphicsEllipseItem::setAdaptiveStepLength ( double theValue ) {
if (adaptiveStepLength == theValue) return;
adaptiveStepLength = theValue;
emit adaptiveStepLengthChanged(theValue);
}