338 lines
11 KiB
C++
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);
|
|
}
|