Files
lsim/src/simulscene.cpp

1157 lines
40 KiB
C++
Raw Normal View History

/***************************************************************************
* 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 "constants.h"
#include "simulscene.h"
#include <QGraphicsRectItem>
#include <QTimeLine>
#include <QGraphicsItemAnimation>
#include <cmath>
#include "graphicsellipseitem.h"
#include "homoefielditem.h"
#include "homobfielditem.h"
#include "stopperitem.h"
#include <QRectF>
#include <QGraphicsSceneMouseEvent>
#include <QtDebug>
#include <QApplication>
#include <QGraphicsRectItem>
#include <QKeyEvent>
#include <QGraphicsItemGroup>
#include <QPainterPath>
#include <QGraphicsPathItem>
#include <QListWidget>
#include <QPainter>
#include <QMap>
#include <QPair>
SimulScene::SimulScene ( QObject* parent ) : QGraphicsScene ( parent ) {
fieldListWidget = new QListWidget();
currHomoEfieldInsertItem = 0;
currHomoEfieldEditItem = 0;
currHomoBfieldInsertItem = 0;
currHomoBfieldEditItem = 0;
currStopperInsertItem = 0;
currStopperEditItem = 0;
ChargePlacementInProgress = false;
createResizeRects();
//path Item Erstellen
pathItem1 = addPath(QPainterPath(), QPen(QColor(255,137,11), 1, Qt::SolidLine));
pathItem1->setZValue(100);
//pathItem1->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
setFlightPathVisible();
/*addLine(0,-298,0,298,QPen(Qt::green, 1, Qt::SolidLine) )->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
addLine(-398,0,398,0,QPen(Qt::green, 1, Qt::SolidLine) )->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
for (int i = -39; i< 39; ++i) {
if(i!=0) {
QGraphicsLineItem *line = addLine(i*10,-298,i*10,298,QPen(Qt::lightGray, 1, Qt::DotLine) );
line->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
line->setZValue(-1);
}
}
for (int i = -29; i< 29; ++i) {
if(i!=0) {
QGraphicsLineItem *line = addLine(-398,i*10,398,i*10,QPen(Qt::lightGray, 1, Qt::DotLine) );
line ->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
line->setZValue(-1);
}
}*/
ellipse1 = new GraphicsEllipseItem();
ellipse1->setRect(-2,-2,5,5);
ellipse1->setPen(Qt::NoPen);
ellipse1->setBrush(Qt::red);
ellipse1->setZValue(200);
//ellipse1->scale(0.25,0.25);
connect(this,SIGNAL(changed(QList<QRectF>)),ellipse1,SLOT(handleSceneChange(QList<QRectF>)));
addItem(ellipse1);
timer = new QTimeLine(1);
timer->setCurveShape(QTimeLine::LinearCurve);
//timer->toggleDirection();
ani = new QGraphicsItemAnimation();
ani->setItem(ellipse1);
ani->setTimeLine(timer);
connect( timer, SIGNAL(finished()), this, SIGNAL(timeLineInRunningState()) );
connect( timer, SIGNAL(valueChanged(qreal)), this, SLOT(handleTimeLineValueChange(qreal)) );
setupVars();
}
void SimulScene::drawBackground ( QPainter * painter, const QRectF & rect ) {
QGraphicsScene::drawBackground(painter,rect);
}
void SimulScene::handleTimeLineValueChange(qreal value ) {
int step = 0;
QList<QPair<qreal, QPointF> > poslist = ani->posList();
for(int i = 1;i<poslist.count() ; ++i ) {
if(value > poslist[i-1].first && value < poslist[i].first) {
step = floor((i-1) * ellipse1->getSpeedListY()->count()/poslist.count());
break;
}
}
//qDebug()<<step <<"-->"<<ellipse1->getSpeedListY()->at(step);
double gesSpeed = sqrt(pow(ellipse1->getSpeedListX()->at(step),2) +pow(ellipse1->getSpeedListY()->at(step),2));
QString newSpeedStringX(QLocale().toString(ellipse1->getSpeedListX()->at(step) ,'g',3));
newSpeedStringX.append(" m/s");
QString newSpeedStringY(QLocale().toString(ellipse1->getSpeedListY()->at(step),'g',3));
newSpeedStringY.append(" m/s");
QString newSpeedGes(QLocale().toString(gesSpeed,'g',3));
newSpeedGes.append(" m/s");
emit probeSpeedXChanged(newSpeedStringX);
emit probespeedYChanged(newSpeedStringY);
emit probeSpeedChanged(newSpeedGes);
ellipse1->updateScenePosLabels();
}
void SimulScene::setupVars() {
//variablen initialisieren
setTimePerStep(1e-10);
setSteps(300000);
//setMeterPerPx(1/1000.0);
setMeterPerPx(0.01);
setPxPerSec(90.0);
timer->setFrameRange(0,100);
//timer->setUpdateInterval(30);
timer->setCurveShape(QTimeLine::LinearCurve);
setTimeLineDuration(30000);
setFlightPathVisible(true);
}
QList<QVariant> SimulScene::getSaveDataList() {
QList<QVariant> list;
list<< getTimePerStep();
list<< getSteps();
list<< getMeterPerPx();
list<< getPxPerSec();
list<< getTimeLineDuration();
list<< isFlightPathVisible();
return list;
}
void SimulScene::setSaveDataList(QList<QVariant> list){
setTimePerStep(list[0].toDouble());
setSteps(list[1].toInt());
setMeterPerPx(list[2].toDouble());
setPxPerSec(list[3].toDouble());
setTimeLineDuration(list[4].toInt());
setFlightPathVisible(list[5].toBool());
}
void SimulScene::startTimer() {
timer->setCurrentTime(0);
timer->start();
}
void SimulScene::stopTimer() {
timer->setCurrentTime(0);
timer->stop();
emit timeLineInRunningState(false);
}
void SimulScene::pauseTimer(bool yesno) {
if (yesno) timer->stop();
else timer->start();
}
void SimulScene::startPauseTimer(bool yesno) {
pauseTimer(!yesno);
}
void SimulScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) {
switch(myMode) {
case HomoEFieldItemInsert:
if (mouseEvent->button() != Qt::LeftButton) break; //benutze nur linke maustaste
currHomoEfieldInsertItem = new HomoEFieldItem(QRectF(mouseEvent->scenePos(),mouseEvent->scenePos()));
currHomoEfieldInsertItem->setZValue(getHighestZIndexFieldItems() + FieldZStep); //zValue setzen
addItem(currHomoEfieldInsertItem);
QApplication::setOverrideCursor(QCursor(Qt::SizeFDiagCursor));
break;
case StopperItemInsert:
if (mouseEvent->button() != Qt::LeftButton) break; //benutze nur linke maustaste
currStopperInsertItem = new StopperItem(mouseEvent->scenePos() ,mouseEvent->scenePos());
currStopperInsertItem->setZValue(getHighestZIndexFieldItems() + FieldZStep); //zValue setzen
addItem(currStopperInsertItem);
QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor));
break;
case HomoBFieldItemInsert:
if (mouseEvent->button() != Qt::LeftButton) break; //benutze nur linke maustaste
currHomoBfieldInsertItem = new HomoBFieldItem(QRectF(mouseEvent->scenePos(),mouseEvent->scenePos()));
currHomoBfieldInsertItem->setZValue(getHighestZIndexFieldItems()+FieldZStep); //zValue setzen
addItem(currHomoBfieldInsertItem);
QApplication::setOverrideCursor(QCursor(Qt::SizeFDiagCursor));
break;
case ProbeChargeItemPlace:
if (mouseEvent->button() != Qt::LeftButton) break; //benutze nur linke maustaste
clearSelection();
ChargePlacementInProgress = true;
ellipse1->setPos(mouseEvent->scenePos());
break;
default:
if (itemAt(mouseEvent->scenePos())->data(0) == ResizeRectItem && mouseEvent->button()==Qt::LeftButton) {
pressedResizeItem = itemAt(mouseEvent->scenePos());
if (selectedItems().first()->type() == HomoEFieldItem::Type) {
currHomoEfieldEditItem = qgraphicsitem_cast<HomoEFieldItem *>(selectedItems().first());
QApplication::setOverrideCursor(pressedResizeItem->cursor());
}
else if (selectedItems().first()->type() == HomoBFieldItem::Type) {
currHomoBfieldEditItem = qgraphicsitem_cast<HomoBFieldItem *>(selectedItems().first());
QApplication::setOverrideCursor(pressedResizeItem->cursor());
}
else if (selectedItems().first()->type() == StopperItem::Type) {
currStopperEditItem = qgraphicsitem_cast<StopperItem *>(selectedItems().first());
QApplication::setOverrideCursor(pressedResizeItem->cursor());
}
}
else {
QGraphicsScene::mousePressEvent(mouseEvent);
}
}
}
void SimulScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) {
if (currHomoEfieldInsertItem != 0) {
if (myMode == HomoEFieldItemInsert) {
QPointF point(currHomoEfieldInsertItem->getRectF().x(), currHomoEfieldInsertItem->getRectF().y());
update(currHomoEfieldInsertItem->getRectF());
if(point.x() <= mouseEvent->scenePos().x() && point.y() <= mouseEvent->scenePos().y()) {
QRectF rect(point,mouseEvent->scenePos());
currHomoEfieldInsertItem->setRectF(rect);
//update(QRectF(point,mouseEvent->lastScenePos()));
}
}
}
if (currStopperInsertItem != 0) {
if (myMode == StopperItemInsert) {
QPointF point(currStopperInsertItem->getRectF().x(), currStopperInsertItem->getRectF().y());
update(currStopperInsertItem->getRectF());
if(point.x() <= mouseEvent->scenePos().x() && point.y() <= mouseEvent->scenePos().y()) {
currStopperInsertItem->setLine(QLineF(point, QPointF(mouseEvent->scenePos().x(),point.y() )));
}
}
}
else if (currHomoBfieldInsertItem != 0) {
if (myMode == HomoBFieldItemInsert) {
QPointF point(currHomoBfieldInsertItem->getRectF().x(), currHomoBfieldInsertItem->getRectF().y());
update(currHomoBfieldInsertItem->getRectF());
if(point.x() <= mouseEvent->scenePos().x() && point.y() <= mouseEvent->scenePos().y()) {
QRectF rect(point,mouseEvent->scenePos());
currHomoBfieldInsertItem->setRectF(rect);
//update(QRectF(point,mouseEvent->lastScenePos()));
}
}
}
else if (currHomoEfieldEditItem != 0 ) {
QGraphicsRectItem *pressedRectItem = qgraphicsitem_cast<QGraphicsRectItem *>(pressedResizeItem);
QRectF currRect = currHomoEfieldEditItem->getRectF();
QPointF newPos = currHomoEfieldEditItem->pos();
calculateItemResize(mouseEvent,pressedRectItem,currRect,newPos,HomoEFieldItem::MinimumWidth,HomoEFieldItem::MinimumHeight);
//aenderungen uebernehmen
currHomoEfieldEditItem->setPos(newPos);
if (currRect != currHomoEfieldEditItem->getRectF()) {
currHomoEfieldEditItem->setRectF(currRect);
}
//resize rechtecke mitverschieben --> macht jetzt schon das Widget
//if(mouseEvent->scenePos() != mouseEvent->lastScenePos()) displayResizeRects(true);
}
else if (currHomoBfieldEditItem != 0 ) {
QGraphicsRectItem *pressedRectItem = qgraphicsitem_cast<QGraphicsRectItem *>(pressedResizeItem);
QRectF currRect = currHomoBfieldEditItem->getRectF();
QPointF newPos = currHomoBfieldEditItem->pos();
calculateItemResize(mouseEvent,pressedRectItem,currRect,newPos,HomoBFieldItem::MinimumWidth,HomoBFieldItem::MinimumHeight);
//aenderungen uebernehmen
currHomoBfieldEditItem->setPos(newPos);
if (currRect != currHomoBfieldEditItem->getRectF()) {
currHomoBfieldEditItem->setRectF(currRect);
}
//resize rechtecke mitverschieben --> macht jetzt schon das Widget
//if(mouseEvent->scenePos() != mouseEvent->lastScenePos()) displayResizeRects(true);
}
else if (currStopperEditItem != 0 ) {
QGraphicsRectItem *pressedRectItem = qgraphicsitem_cast<QGraphicsRectItem *>(pressedResizeItem);
QRectF currRect = currStopperEditItem->getRectF();
QPointF pos = currStopperEditItem->pos();
//calculateItemResize(mouseEvent,pressedRectItem,currRect,newPos,StopperItem::MinimumWidth,StopperItem::Height);
qreal mouseDistanceX = mouseEvent->scenePos().x() - mouseEvent->lastScenePos().x();
//aenderungen uebernehmen
if (
pressedResizeItem == reRects.rightRezizeItem ||
pressedResizeItem == reRects.rightTopResizeItem ||
pressedResizeItem == reRects.rightBottomResizeItem
) {
QPointF newPos = QPointF(pos.x()+currRect.width()+mouseDistanceX , pos.y());
if (newPos.x() - pos.x() >= StopperItem::MinimumWidth) {
currRect.adjust(0,0, (mouseDistanceX),0);
currStopperEditItem->setRectF(currRect);
//currStopperEditItem->setLine(QLineF(pos, newPos ));
}
} else if (
pressedResizeItem == reRects.leftResizeItem ||
pressedResizeItem == reRects.leftTopResizeItem ||
pressedResizeItem == reRects.leftBottomResizeItem
) {
if ( pos.x() - pos.x()+currRect.width()-mouseDistanceX >= StopperItem::MinimumWidth) {
currRect.adjust(0,0,-mouseDistanceX,0);
currStopperEditItem->setPos(pos.x()+mouseDistanceX,pos.y());
currStopperEditItem->setRectF(currRect);
//currStopperEditItem->setLine(QLineF(pos, newPos ));
}
}
//resize rechtecke mitverschieben --> macht jetzt schon das Widget
//if(mouseEvent->scenePos() != mouseEvent->lastScenePos()) displayResizeRects(true);
}
else if (ChargePlacementInProgress) {
if (myMode == ProbeChargeItemPlace) {
ellipse1->setPos(mouseEvent->scenePos());
}
}
else {
QGraphicsScene::mouseMoveEvent(mouseEvent);
if (mouseEvent->buttons() == Qt::LeftButton)
if(mouseEvent->scenePos() != mouseEvent->lastScenePos())
displayResizeRects(true);
}
}
void SimulScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) {
if (currHomoEfieldInsertItem != 0 && myMode == HomoEFieldItemInsert) {
if (currHomoEfieldInsertItem->getRectF().width() < HomoEFieldItem::MinimumWidth || currHomoEfieldInsertItem->getRectF().height() <HomoEFieldItem::MinimumHeight ) {
//removeItem(currHomoEfieldInsertItem); //segmention fault in kombination mit delete?
delete currHomoEfieldInsertItem; //zu kleines feld loeschen
}
else {
//setze Startpunkt des rechtecks auf 0,0, damit pos() richtig funktioniert
currHomoEfieldInsertItem->setVisible(false); //ausblenden, damit sich nix verschiebt
QRectF rect (currHomoEfieldInsertItem->getRectF());
QPointF posPoint(rect.x(),rect.y());
rect.setWidth(rect.width() - rect.x());
rect.setHeight(rect.height() - rect.y());
rect.setX(0);
rect.setY(0);
currHomoEfieldInsertItem->setRectF(rect);
currHomoEfieldInsertItem->setPos(posPoint);
currHomoEfieldInsertItem->setVisible(true); //und wieder einblenden
setSceneMode(FieldItemEdit);
//das neue item auswaehlen
clearSelection();
currHomoEfieldInsertItem->setSelected(true);
//die resize items aus und einblenden bei rotation
connect( currHomoEfieldInsertItem, SIGNAL(rotationChanged()), this, SLOT(displayResizeRects()));
//bei groesenanderung und verschieben resizerects mitverschieben
connect( currHomoEfieldInsertItem, SIGNAL(heightChanged(double)), this, SLOT(moveResizeRects()));
connect( currHomoEfieldInsertItem, SIGNAL(widthChanged(double)), this, SLOT(moveResizeRects()));
connect( currHomoEfieldInsertItem, SIGNAL(ScenePosChanged(QPointF)), this, SLOT(moveResizeRects()));
//item ueber sceneChange informieren
connect(this,SIGNAL(changed(QList<QRectF>)),currHomoEfieldInsertItem,SLOT(handleSceneChange(QList<QRectF>)));
}
update(); //moegliche darstellungsprobleme beseitigen
QApplication::restoreOverrideCursor();
}
else if (currHomoBfieldInsertItem != 0 && myMode == HomoBFieldItemInsert) {
if (currHomoBfieldInsertItem->getRectF().width() < HomoBFieldItem::MinimumWidth || currHomoBfieldInsertItem->getRectF().height() <HomoBFieldItem::MinimumHeight ) {
//removeItem(currHomoEfieldInsertItem); //segmention fault in kombination mit delete?
delete currHomoBfieldInsertItem; //zu kleines feld loeschen
}
else {
//setze Startpunkt des rechtecks auf 0,0, damit pos() richtig funktioniert
currHomoBfieldInsertItem->setVisible(false); //ausblenden, damit sich nix verschiebt
QRectF rect (currHomoBfieldInsertItem->getRectF());
QPointF posPoint(rect.x(),rect.y());
rect.setWidth(rect.width() - rect.x());
rect.setHeight(rect.height() - rect.y());
rect.setX(0);
rect.setY(0);
currHomoBfieldInsertItem->setRectF(rect);
currHomoBfieldInsertItem->setPos(posPoint);
currHomoBfieldInsertItem->setVisible(true); //und wieder einblenden
setSceneMode(FieldItemEdit);
//das neue item auswaehlen
clearSelection();
currHomoBfieldInsertItem->setSelected(true);
//die resize items aus und einblenden bei rotation
connect( currHomoBfieldInsertItem, SIGNAL(rotationChanged()), this, SLOT(displayResizeRects()));
//bei groesenanderung und verschieben resizerects mitverschieben
connect( currHomoBfieldInsertItem, SIGNAL(heightChanged(double)), this, SLOT(moveResizeRects()));
connect( currHomoBfieldInsertItem, SIGNAL(widthChanged(double)), this, SLOT(moveResizeRects()));
connect( currHomoBfieldInsertItem, SIGNAL(ScenePosChanged(QPointF)), this, SLOT(moveResizeRects()));
//item ueber sceneChange informieren
connect(this,SIGNAL(changed(QList<QRectF>)),currHomoBfieldInsertItem,SLOT(handleSceneChange(QList<QRectF>)));
}
update(); //moegliche darstellungsprobleme beseitigen
QApplication::restoreOverrideCursor();
}
else if (currStopperInsertItem != 0 && myMode == StopperItemInsert) {
if (currStopperInsertItem->getRectF().width() < StopperItem::MinimumWidth) {
//removeItem(currHomoEfieldInsertItem); //segmention fault in kombination mit delete?
delete currStopperInsertItem; //zu kleines feld loeschen
} else {
//setze Startpunkt des rechtecks auf 0,0, damit pos() richtig funktioniert
currStopperInsertItem->setVisible(false); //ausblenden, damit sich nix verschiebt
QRectF rect (currStopperInsertItem->getRectF());
QPointF posPoint(rect.x(),rect.y());
rect.setWidth(rect.width() - rect.x());
rect.setHeight(rect.height() - rect.y());
rect.setX(0);
rect.setY(0);
currStopperInsertItem->setRectF(rect);
currStopperInsertItem->setPos(posPoint);
currStopperInsertItem->setVisible(true); //und wieder einblenden
setSceneMode(FieldItemEdit);
//das neue item auswaehlen
clearSelection();
currStopperInsertItem->setSelected(true);
//die resize items aus und einblenden bei rotation
connect( currStopperInsertItem, SIGNAL(rotationChanged()), this, SLOT(displayResizeRects()));
//bei groesenanderung und verschieben resizerects mitverschieben
connect( currStopperInsertItem, SIGNAL(heightChanged(double)), this, SLOT(moveResizeRects()));
connect( currStopperInsertItem, SIGNAL(widthChanged(double)), this, SLOT(moveResizeRects()));
connect( currStopperInsertItem, SIGNAL(ScenePosChanged(QPointF)), this, SLOT(moveResizeRects()));
//item ueber sceneChange informieren
connect(this,SIGNAL(changed(QList<QRectF>)),currStopperInsertItem,SLOT(handleSceneChange(QList<QRectF>)));
}
update(); //moegliche darstellungsprobleme beseitigen
QApplication::restoreOverrideCursor();
}
else if (currHomoEfieldEditItem != 0) {
update();
QApplication::restoreOverrideCursor();
}
else if (currHomoBfieldEditItem != 0) {
update();
QApplication::restoreOverrideCursor();
}
else if (currStopperEditItem != 0) {
update();
QApplication::restoreOverrideCursor();
}
else if (ChargePlacementInProgress) {
ChargePlacementInProgress = false;
setSceneMode(FieldItemEdit);
}
pressedResizeItem = 0;
currHomoEfieldInsertItem = 0;
currHomoBfieldInsertItem = 0;
currHomoEfieldEditItem = 0;
currHomoBfieldEditItem = 0;
currStopperInsertItem = 0;
currStopperEditItem = 0;
QGraphicsScene::mouseReleaseEvent(mouseEvent);
}
void SimulScene::keyPressEvent (QKeyEvent *keyevent) {
if(keyevent->matches(QKeySequence::Delete)) {
deleteSelectedFieldItems();
}
}
void SimulScene::setSceneMode(SceneMode mode) {
if(myMode==mode) return;
myMode = mode;
emit sceneModeChanged(mode);
}
void SimulScene::createResizeRects() {
const QRectF resizeRectSize(0,0,7,7);
reRects.leftTopResizeItem = new QGraphicsRectItem(resizeRectSize);
reRects.leftTopResizeItem->setCursor(Qt::SizeFDiagCursor);
reRects.leftTopResizeItem->setBrush(Qt::black);
reRects.leftTopResizeItem->setVisible(false);
reRects.leftTopResizeItem->setData(0, QVariant(ResizeRectItem)); //typ des items setzen
reRects.leftResizeItem = new QGraphicsRectItem(resizeRectSize);
reRects.leftResizeItem->setCursor(Qt::SizeHorCursor);
reRects.leftResizeItem->setBrush(Qt::black);
reRects.leftResizeItem->setVisible(false);
reRects.leftResizeItem->setData(0, QVariant(ResizeRectItem));
reRects.leftBottomResizeItem = new QGraphicsRectItem(resizeRectSize);
reRects.leftBottomResizeItem->setCursor(Qt::SizeBDiagCursor);
reRects.leftBottomResizeItem->setBrush(Qt::black);
reRects.leftBottomResizeItem->setVisible(false);
reRects.leftBottomResizeItem->setData(0, QVariant(ResizeRectItem));
reRects.bottomResizeItem = new QGraphicsRectItem(resizeRectSize);
reRects.bottomResizeItem->setCursor(Qt::SizeVerCursor);
reRects.bottomResizeItem->setBrush(Qt::black);
reRects.bottomResizeItem->setVisible(false);
reRects.bottomResizeItem->setData(0, QVariant(ResizeRectItem));
reRects.rightBottomResizeItem = new QGraphicsRectItem(resizeRectSize);
reRects.rightBottomResizeItem->setCursor(Qt::SizeFDiagCursor);
reRects.rightBottomResizeItem->setBrush(Qt::black);
reRects.rightBottomResizeItem->setVisible(false);
reRects.rightBottomResizeItem->setData(0, QVariant(ResizeRectItem));
reRects.rightRezizeItem = new QGraphicsRectItem(resizeRectSize);
reRects.rightRezizeItem->setCursor(Qt::SizeHorCursor);
reRects.rightRezizeItem->setBrush(Qt::black);
reRects.rightRezizeItem->setVisible(false);
reRects.rightRezizeItem->setData(0, QVariant(ResizeRectItem));
reRects.rightTopResizeItem = new QGraphicsRectItem(resizeRectSize);
reRects.rightTopResizeItem->setCursor(Qt::SizeBDiagCursor);
reRects.rightTopResizeItem->setBrush(Qt::black);
reRects.rightTopResizeItem->setVisible(false);
reRects.rightTopResizeItem->setData(0, QVariant(ResizeRectItem));
reRects.topResizeItem = new QGraphicsRectItem(resizeRectSize);
reRects.topResizeItem->setCursor(Qt::SizeVerCursor);
reRects.topResizeItem->setBrush(Qt::black);
reRects.topResizeItem->setVisible(false);
reRects.topResizeItem->setData(0, QVariant(ResizeRectItem));
addItem(reRects.leftTopResizeItem);
addItem(reRects.leftResizeItem);
addItem(reRects.leftBottomResizeItem);
addItem(reRects.bottomResizeItem);
addItem(reRects.rightBottomResizeItem);
addItem(reRects.rightRezizeItem);
addItem(reRects.rightTopResizeItem);
addItem(reRects.topResizeItem);
connect( this, SIGNAL(selectionChanged()), this, SLOT(displayResizeRects()) );
}
void SimulScene::displayResizeRects(bool move) {
if (
selectedItems().count() == 1 &&
FieldItem::isFieldItem(selectedItems().first()) &&
!selectedItems().first()->transform().isTranslating() //bei rotation nicht anzeigen
) {
const qreal oSPACE = 3; //Aussenabstand
//position des ausgewaehlten items
QPointF seletedPos = selectedItems().first()->pos();
qreal selPosX = seletedPos.x();
qreal selPosY = seletedPos.y();
//an die richtige stelle schieben
reRects.leftTopResizeItem->setPos(selPosX - reRects.leftTopResizeItem->rect().width()- oSPACE,
selPosY - reRects.leftTopResizeItem->rect().height() - oSPACE);
reRects.leftResizeItem->setPos(selPosX - reRects.leftResizeItem->rect().width()- oSPACE,
selPosY +
selectedItems().first()->boundingRect().height() / 2.0 -
reRects.leftResizeItem->rect().height() /2.0);
reRects.leftBottomResizeItem->setPos(selPosX - reRects.leftBottomResizeItem->rect().width()- oSPACE,
selPosY + selectedItems().first()->boundingRect().height() + oSPACE);
reRects.bottomResizeItem->setPos(selPosX +
selectedItems().first()->boundingRect().width() / 2.0 -
reRects.bottomResizeItem->rect().width() /2.0,
selPosY + selectedItems().first()->boundingRect().height() + oSPACE);
reRects.rightBottomResizeItem->setPos(selPosX + selectedItems().first()->boundingRect().width() + oSPACE,
selPosY + selectedItems().first()->boundingRect().height() + oSPACE);
reRects.rightRezizeItem->setPos(selPosX + selectedItems().first()->boundingRect().width() + oSPACE,
selPosY +
selectedItems().first()->boundingRect().height() / 2.0 -
reRects.rightRezizeItem->rect().height() /2.0);
reRects.rightTopResizeItem->setPos(selPosX + selectedItems().first()->boundingRect().width() + oSPACE,
selPosY - reRects.rightTopResizeItem->rect().height() - oSPACE);
reRects.topResizeItem->setPos(selPosX +
selectedItems().first()->boundingRect().width() / 2.0 -
reRects.topResizeItem->rect().width() /2.0,
selPosY - reRects.leftTopResizeItem->rect().height() - oSPACE);
if (!move) { //im verschiebemodus kann man von diesen dingen ausgehen
//nach oben bringen
qreal newZValue = getHighestZIndexVisible() + 0.000001;
reRects.leftTopResizeItem->setZValue(newZValue);
reRects.leftResizeItem->setZValue(newZValue);
reRects.leftBottomResizeItem->setZValue(newZValue);
reRects.bottomResizeItem->setZValue(newZValue);
reRects.rightBottomResizeItem->setZValue(newZValue);
reRects.rightRezizeItem->setZValue(newZValue);
reRects.rightTopResizeItem->setZValue(newZValue);
reRects.topResizeItem->setZValue(newZValue);
//sichtbar machen
reRects.leftTopResizeItem->setVisible(true);
reRects.leftResizeItem->setVisible(true);
reRects.leftBottomResizeItem->setVisible(true);
reRects.bottomResizeItem->setVisible(true);
reRects.rightBottomResizeItem->setVisible(true);
reRects.rightRezizeItem->setVisible(true);
reRects.rightTopResizeItem->setVisible(true);
reRects.topResizeItem->setVisible(true);
}
}
else if(!move && reRects.leftTopResizeItem->isVisible()) {
//unsichtbar machen
reRects.leftTopResizeItem->setVisible(false);
reRects.leftResizeItem->setVisible(false);
reRects.leftBottomResizeItem->setVisible(false);
reRects.bottomResizeItem->setVisible(false);
reRects.rightBottomResizeItem->setVisible(false);
reRects.rightRezizeItem->setVisible(false);
reRects.rightTopResizeItem->setVisible(false);
reRects.topResizeItem->setVisible(false);
}
}
void SimulScene::moveResizeRects() {
displayResizeRects(true);
}
qreal SimulScene::getHighestZIndexVisible() {
bool highestZValueSet = false;
qreal highestZValue = 0;
for (int i = 0; i < items().count() ; ++i ) {
if (items().at(i)->isVisible()) {
if (!highestZValueSet) {
highestZValue = items().at(i)->zValue();
highestZValueSet = true;
}
else if (highestZValue < items().at(i)->zValue()) {
highestZValue = items().at(i)->zValue();
}
}
}
return highestZValue;
}
qreal SimulScene::getHighestZIndexFieldItems() {
bool highestZValueSet = false;
qreal highestZValue = FieldDefaultZValue; //default value
for (int i = 0; i < items().count() ; ++i ) {
if (FieldItem::isFieldItem(items().at(i))) {
if (!highestZValueSet) {
highestZValue = items().at(i)->zValue();
highestZValueSet = true;
}
else if (highestZValue < items().at(i)->zValue()) {
highestZValue = items().at(i)->zValue();
}
}
}
return highestZValue;
}
qreal SimulScene::getLowestZIndexFieldItems() {
bool lowestZValueSet = false;
qreal lowestZValue = FieldDefaultZValue; //default value
for (int i = 0; i < items().count() ; ++i ) {
if (FieldItem::isFieldItem(items().at(i))) {
if (!lowestZValueSet) {
lowestZValue = items().at(i)->zValue();
lowestZValueSet = true;
}
else if (lowestZValue > items().at(i)->zValue()) {
lowestZValue = items().at(i)->zValue();
}
}
}
return lowestZValue;
}
void SimulScene::deleteSelectedFieldItems() {
QList<QGraphicsItem *> currSelectedItems = selectedItems();
for (int i = 0; i < currSelectedItems.count() ; ++i ) {
if (FieldItem::isFieldItem(currSelectedItems.at(i))) {
delete currSelectedItems.at(i);
}
}
}
void SimulScene::calculateItemResize(
QGraphicsSceneMouseEvent *mouseEvent,
QGraphicsRectItem *pressedRectItem,
QRectF &currRect,
QPointF &newPos,
qreal minWidth,
qreal minHeight
) {
qreal mouseDistanceX = mouseEvent->scenePos().x() - mouseEvent->lastScenePos().x();
qreal mouseDistanceY = mouseEvent->scenePos().y() - mouseEvent->lastScenePos().y();
if (reRects.rightRezizeItem == pressedRectItem) {
currRect.adjust(0,0,mouseDistanceX , 0);
}
else if (reRects.leftResizeItem == pressedRectItem) {
newPos = QPointF(newPos.x()+mouseDistanceX,newPos.y());
currRect.adjust(0,0,-mouseDistanceX , 0);
}
else if (reRects.topResizeItem == pressedRectItem) {
newPos = QPointF(newPos.x(),newPos.y()+mouseDistanceY);
currRect.adjust(0,0,0, -mouseDistanceY );
}
else if (reRects.bottomResizeItem == pressedRectItem) {
currRect.adjust(0,0,0, mouseDistanceY );
}
else if (reRects.rightBottomResizeItem == pressedRectItem) {
currRect.adjust(0,0,0, mouseDistanceY );
currRect.adjust(0,0,mouseDistanceX , 0);
}
else if (reRects.leftBottomResizeItem == pressedRectItem) {
currRect.adjust(0,0,0, mouseDistanceY );
newPos = QPointF(newPos.x()+mouseDistanceX,newPos.y());
currRect.adjust(0,0,-mouseDistanceX , 0);
}
else if (reRects.leftTopResizeItem == pressedRectItem) {
newPos = QPointF(newPos.x(),newPos.y()+mouseDistanceY);
currRect.adjust(0,0,0, -mouseDistanceY );
newPos = QPointF(newPos.x()+mouseDistanceX,newPos.y());
currRect.adjust(0,0,-mouseDistanceX , 0);
}
else if (reRects.rightTopResizeItem == pressedRectItem) {
newPos = QPointF(newPos.x(),newPos.y()+mouseDistanceY);
currRect.adjust(0,0,0, -mouseDistanceY );
currRect.adjust(0,0,mouseDistanceX , 0);
}
//gegen zu klein werden
if (currRect.width() <= minWidth) {
if (mouseEvent->lastScenePos().x() < mouseEvent->scenePos().x()) { //gegen rumspringen
newPos = QPointF(newPos.x() + (currRect.width() - minWidth) ,newPos.y());
}
currRect.setWidth(minWidth);
}
if (currRect.height() <= minHeight) {
if (mouseEvent->lastScenePos().y() < mouseEvent->scenePos().y()) { //gegen rumspringen
newPos = QPointF(newPos.x(), newPos.y() + (currRect.height() - minHeight));
}
currRect.setHeight(minHeight);
}
}
SimulScene::~SimulScene() {
}
/*!
\fn SimulScene::getTimePerStep()
*/
double SimulScene::getTimePerStep() {
return timePerStep;
}
/*!
\fn SimulScene::setTimePerStep(int time)
*/
void SimulScene::setTimePerStep(double time) {
if (time == timePerStep) return;
timePerStep = time;
emit timePerStepChanged(time);
}
/*!
\fn SimulScene::startCalculation()
*/
void SimulScene::startCalculation() {
//evtl laufenden timer stoppen
stopTimer();
//leeren Pfad setezen
clearFlightPath();
//Feld Item Listen erzeugen (viel schneller, als jedes mal items(point) durchlaufen)
calcEFieldList.clear();
calcBFieldList.clear();
calcStopperList.clear();
for(int i = 0; i < items().size(); ++i) {
//HomoEFieldItems Abarbeiten
if (qgraphicsitem_cast<HomoEFieldItem*> (items().at(i)) != 0) {
calcEFieldList << qgraphicsitem_cast<HomoEFieldItem*> (items().at(i));
}
//HomoBFieldItems Abarbeiten
if (qgraphicsitem_cast<HomoBFieldItem*> (items().at(i)) != 0) {
calcBFieldList << qgraphicsitem_cast<HomoBFieldItem*>(items().at(i));
}
//StopperItems Abarbeiten
if (qgraphicsitem_cast<StopperItem*> (items().at(i)) != 0) {
calcStopperList << qgraphicsitem_cast<StopperItem*>(items().at(i));
}
}
//berechnung starten
ellipse1->calculateProbePath(ellipse1->pos());
pathItem1->setPath(ellipse1->getFlightPath());
//animationspfad berechnen
ani->clear();
int currSteps = ellipse1->getCurrProbePath()->count();
int entry_step = ceil(currSteps/2500.0); //jeder entry_step(te) step wird eingetragen
double totalTime = ellipse1->getElapsedTimeList()->at(currSteps-1);
aniStepList.clear();
for (int i=0; i<currSteps; ++i) {
if (i%entry_step == 0 || i==currSteps) {
//Zeianteil
double newStep = ellipse1->getElapsedTimeList()->at(i)/totalTime;
ani->setPosAt(newStep, ellipse1->getCurrProbePath()->at(i) );
//aniStepList.insert(ani->, i);
}
}
//aenderungen bestimmter Werte bekanntgeben
QString realSimulTimeString(QLocale().toString(totalTime,'g'));
realSimulTimeString.append(" s");
emit realSimulTimeChanged(realSimulTimeString);
//brauchbare Animationsdauer bestimmen
setTimeLineDuration(ellipse1->getFlightPath().length()/getPxPerSec() * 1000.0);
}
/*!
\fn SimulScene::getSteps()
*/
int SimulScene::getSteps() {
return steps;
}
/*!
\fn SimulScene::setSteps()
*/
void SimulScene::setSteps(int steps) {
if (this->steps == steps) return;
this->steps = steps;
emit stepsChanged(steps);
}
double SimulScene::getPowerAt(QPointF point, double charge, double speedX, double speedY, char xy) {
double dPower = 0;
for (int i=0; i<calcEFieldList.size(); ++i) {
//HomoEFieldItems Abarbeiten
HomoEFieldItem* myHomoEFieldItem = calcEFieldList.at(i);
if (myHomoEFieldItem->contains(myHomoEFieldItem->mapFromScene(point))) {
double power = (myHomoEFieldItem->getFieldPower() * charge);
double degAngle = myHomoEFieldItem->getRotation();
double radAngle = degAngle/180.0*PI;
if(xy == 'x') {
if (degAngle != 180.0) dPower += power * -sin(radAngle);
}
if(xy == 'y') {
if (degAngle != 90.0 && degAngle != 270.0) dPower += power * cos(radAngle);
}
}
}
for (int i=0; i<calcBFieldList.size(); ++i) {
//HomoBFieldItems Abarbeiten
HomoBFieldItem* myHomoBFieldItem = calcBFieldList.at(i);
if (myHomoBFieldItem->contains(myHomoBFieldItem->mapFromScene(point))) {
double absSpeed = sqrt(speedX * speedX + speedY * speedY); // Geschwindigkeit im Betrag |v|=sqrt(vx^2+vy^2)
double absLorentzPower = (charge * absSpeed * myHomoBFieldItem->getFluxDensity() ); //Kraft im Betrag: |F| = q*v*B
double speedRadAngle = atan2(speedY,speedX); //Winkel des Geschwindigkeitsvekors zur x-Achse im Bogenmass
double PowerRadAngle; //Winkel des Lorentzkraftvektors zur x-Achse im Bogenmass
if (myHomoBFieldItem->getIsDirectionIntoPlane()) {
PowerRadAngle = speedRadAngle - PI/2.0;
} else {
PowerRadAngle = speedRadAngle + PI/2.0;
}
//qDebug()<< PowerRadAngle;
if (xy == 'x') {
dPower += absLorentzPower * cos(PowerRadAngle);
}
if (xy == 'y') {
dPower += absLorentzPower * sin(PowerRadAngle);
}
}
}
return dPower;
}
bool SimulScene::stopsHere(const QPointF &p1, const QPointF &p2) {
QPainterPath myPath(p1);
myPath.lineTo(p2);
for (int i = 0; i< calcStopperList.count(); ++i) {
QPainterPath itemPath = calcStopperList.at(i)->mapFromScene(myPath);
if (calcStopperList.at(i)->collidesWithPath(itemPath/*,Qt::IntersectsItemShape*/)) return true;
}
return false;
}
double SimulScene::getMeterPerPx() const {
return meterPerPx;
}
double SimulScene::getPxPerSec() const {
return pxPerSec;
}
void SimulScene::setMeterPerPx ( double theValue ) {
if (theValue == meterPerPx) return;
meterPerPx = theValue;
emit meterPerPxChanged(theValue);
}
void SimulScene::setPxPerSec ( double theValue ) {
if (theValue == pxPerSec) return;
pxPerSec = theValue;
setTimeLineDuration(ellipse1->getFlightPath().length()/getPxPerSec() * 1000.0);
emit pxPerSecChanged(theValue);
}
/*!
\fn SimulScene::getProbeDockWidget() const
*/
QWidget* SimulScene::getProbeDockWidget() const {
return ellipse1->getDockWidget();
}
void SimulScene::setFlightPathVisible(bool visible) {
if(pathItem1->isVisible() == visible) return;
pathItem1->setVisible(visible);
emit flightPathVisibilityChanged(visible);
}
bool SimulScene::isFlightPathVisible() {
return pathItem1->isVisible();
}
void SimulScene::setTimeLineDuration(int duration) {
if(timer->duration() == duration) return;
timer->setDuration(duration);
emit timeLineDurationChanged(duration);
}
int SimulScene::getTimeLineDuration() {
return timer->duration();
}
QListWidget* SimulScene::getFieldListWidget() {
return fieldListWidget;
}
QList<QGraphicsItem*> SimulScene::getItemsInZOrder() {
QList<QGraphicsItem*> currItems = items();
bool swapNeeded;
for (int i=0;i< currItems.count();++i) {
swapNeeded=false;
for (int j=0; j< currItems.count() -i -1; ++j){
if(currItems[j]->zValue() > currItems[j+1]->zValue()) {
QGraphicsItem* swapper = currItems[j];
currItems[j]= currItems[j+1];
currItems[j+1] = swapper;
swapNeeded = true;
}
}
if(!swapNeeded) break;
}
return currItems;
}
QList<QGraphicsItem*> SimulScene::getFieldItemsInZOrder() {
QList<QGraphicsItem*> currItems;
for (int i = 0; i< items().size();++i) {
if(FieldItem::isFieldItem(items().at(i))) currItems.append(items().at(i));
}
bool swapNeeded;
for (int i=0;i< currItems.count();++i) {
swapNeeded=false;
for (int j=0; j< currItems.count() -i -1; ++j){
if(currItems[j]->zValue() > currItems[j+1]->zValue()) {
QGraphicsItem* swapper = currItems[j];
currItems[j]= currItems[j+1];
currItems[j+1] = swapper;
swapNeeded = true;
}
}
if(!swapNeeded) break;
}
//for (int i=0;i< currItems.count();++i) {
// qDebug()<< "sort: " <<currItems[i]->zValue();
//}
return currItems;
}
void SimulScene::moveFieldItemDown(QGraphicsItem* fieldItem) {
if (!FieldItem::isFieldItem(fieldItem)) return;
qreal currFieldItemZValue = fieldItem->zValue();
QList<QGraphicsItem*> FieldItemsInZOrder = getFieldItemsInZOrder();
for (int i = 1; i< FieldItemsInZOrder.count();++i) {
if (FieldItemsInZOrder.at(i) == fieldItem) {
fieldItem->setZValue(FieldItemsInZOrder.at(i-1)->zValue());
FieldItemsInZOrder.at(i-1)->setZValue(currFieldItemZValue);
return;
}
}
}
void SimulScene::moveFieldItemUp(QGraphicsItem* fieldItem) {
if (!FieldItem::isFieldItem(fieldItem)) return;
qreal currFieldItemZValue = fieldItem->zValue();
QList<QGraphicsItem*> FieldItemsInZOrder = getFieldItemsInZOrder();
for (int i = 0; i< FieldItemsInZOrder.count()-1;++i) {
if (FieldItemsInZOrder.at(i) == fieldItem) {
fieldItem->setZValue(FieldItemsInZOrder.at(i+1)->zValue());
FieldItemsInZOrder.at(i+1)->setZValue(currFieldItemZValue);
return;
}
}
}
void SimulScene::moveFieldItemOnTop(QGraphicsItem* fieldItem) {
if (!FieldItem::isFieldItem(fieldItem)) return;
qreal currFieldItemZValue = fieldItem->zValue();
QList<QGraphicsItem*> FieldItemsInZOrder = getFieldItemsInZOrder();
bool fieldItemHit = false;
for (int i = 0; i< FieldItemsInZOrder.count()-1;++i) {//currItem rauf wandern lassen
if (FieldItemsInZOrder.at(i) == fieldItem) {
fieldItemHit = true;
}
if (fieldItemHit) {
QGraphicsItem* swapper = FieldItemsInZOrder.at(i);
FieldItemsInZOrder[i] = FieldItemsInZOrder.at(i+1);
FieldItemsInZOrder[i+1] = swapper;
}
}
for (int i = 0;i<FieldItemsInZOrder.count();++i) { //z-index fuer neue reihenfolge setzen
FieldItemsInZOrder[i]->setZValue( (FieldDefaultZValue + i*FieldZStep));
}
}
void SimulScene::moveFieldItemOnBottom(QGraphicsItem* fieldItem) {
if (!FieldItem::isFieldItem(fieldItem)) return;
qreal currFieldItemZValue = fieldItem->zValue();
QList<QGraphicsItem*> FieldItemsInZOrder = getFieldItemsInZOrder();
bool fieldItemHit = false;
for (int i = FieldItemsInZOrder.count()-1; i>0 ;--i) { //currItem runter wandern lassen
if (FieldItemsInZOrder.at(i) == fieldItem) {
fieldItemHit = true;
}
if (fieldItemHit) {
QGraphicsItem* swapper = FieldItemsInZOrder.at(i);
FieldItemsInZOrder[i] = FieldItemsInZOrder.at(i-1);
FieldItemsInZOrder[i-1] = swapper;
}
}
for (int i = 0;i<FieldItemsInZOrder.count();++i) { //z-index fuer neue reihenfolge setzen
FieldItemsInZOrder[i]->setZValue( (FieldDefaultZValue + i*FieldZStep));
}
}
void SimulScene::moveSelectedFieldItemDown() {
if (selectedItems().isEmpty()) return;
moveFieldItemDown(selectedItems().first());
}
void SimulScene::moveSelectedFieldItemUp() {
if (selectedItems().isEmpty()) return;
moveFieldItemUp(selectedItems().first());
}
void SimulScene::moveSelectedFieldItemOnTop() {
if (selectedItems().isEmpty()) return;
moveFieldItemOnTop(selectedItems().first());
}
void SimulScene::moveSelectedFieldItemOnBottom() {
if (selectedItems().isEmpty()) return;
moveFieldItemOnBottom(selectedItems().first());
}
GraphicsEllipseItem* SimulScene::getProbeChargeItem() {
return ellipse1;
}
void SimulScene::clearFlightPath() {
pathItem1->setPath(QPainterPath());
}
void SimulScene::resetScene() {
//Alle felder Entfernen
QList<QGraphicsItem*> currItems = items();
for (int i = 0; i<currItems.count();++i)
if(FieldItem::isFieldItem(currItems.at(i)) )
delete currItems.at(i);
setupVars();
ellipse1->resetProbe();
}