pxmlw6n2f/Gazebo_Distributed_TCP/gazebo/gui/building/RectItem.cc

1042 lines
30 KiB
C++

/*
* Copyright (C) 2012 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <ignition/math/Angle.hh>
#include "gazebo/gui/Conversions.hh"
#include "gazebo/gui/building/BuildingEditorWidget.hh"
#include "gazebo/gui/building/GrabberHandle.hh"
#include "gazebo/gui/building/MeasureItem.hh"
#include "gazebo/gui/building/RectItem.hh"
#include "gazebo/gui/building/RectItemPrivate.hh"
#include "gazebo/gui/building/RotateHandle.hh"
#include "gazebo/gui/building/WallSegmentItem.hh"
using namespace gazebo;
using namespace gui;
/////////////////////////////////////////////////
RectItem::RectItem() : EditorItem(), dataPtr(new RectItemPrivate())
{
this->editorType = "Rect";
this->width = 100;
this->height = 100;
this->highlighted = true;
this->drawingOriginX = 0;
this->drawingOriginY = 0;
this->dataPtr->positionOnWall = 0;
this->dataPtr->angleOnWall = 0;
this->drawingWidth = this->width;
this->drawingHeight = this->height;
this->borderColor = common::Color::Black;
for (int i = 0; i < 8; ++i)
{
GrabberHandle *grabber = new GrabberHandle(this, i);
this->dataPtr->grabbers.push_back(grabber);
}
this->dataPtr->rotateHandle = new RotateHandle(this);
this->setSelected(false);
this->setFlags(this->flags() | QGraphicsItem::ItemIsSelectable);
this->setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
this->UpdateCornerPositions();
this->setAcceptHoverEvents(true);
this->dataPtr->cursors.push_back(Qt::SizeFDiagCursor);
this->dataPtr->cursors.push_back(Qt::SizeVerCursor);
this->dataPtr->cursors.push_back(Qt::SizeBDiagCursor);
this->dataPtr->cursors.push_back(Qt::SizeHorCursor);
this->setCursor(Qt::SizeAllCursor);
this->rotationAngle = 0;
this->zValueIdle = 1;
this->zValueSelected = 5;
this->SetResizeFlag(ITEM_WIDTH | ITEM_HEIGHT);
this->openInspectorAct = new QAction(tr("&Open Inspector"), this);
this->openInspectorAct->setStatusTip(tr("Open Inspector"));
connect(this->openInspectorAct, SIGNAL(triggered()),
this, SLOT(OnOpenInspector()));
this->deleteItemAct = new QAction(tr("&Delete"), this);
this->deleteItemAct->setStatusTip(tr("Delete"));
connect(this->deleteItemAct, SIGNAL(triggered()),
this, SLOT(OnDeleteItem()));
}
/////////////////////////////////////////////////
RectItem::~RectItem()
{
for (int i = 0; i < 8; ++i)
{
this->dataPtr->grabbers[i]->setParentItem(NULL);
delete this->dataPtr->grabbers[i];
}
this->dataPtr->rotateHandle->setParentItem(NULL);
delete this->dataPtr->rotateHandle;
if (!this->parentItem() && !this->measures.empty())
{
delete this->measures[0];
delete this->measures[1];
}
}
/////////////////////////////////////////////////
void RectItem::ShowHandles(bool _show)
{
for (int i = 0; i < 8; ++i)
{
this->dataPtr->grabbers[i]->setVisible(_show &&
this->dataPtr->grabbers[i]->isEnabled());
}
this->dataPtr->rotateHandle->setVisible(_show);
}
/////////////////////////////////////////////////
void RectItem::AdjustSize(double _x, double _y)
{
this->width += _x;
this->height += _y;
this->drawingWidth = this->width;
this->drawingHeight = this->height;
}
/////////////////////////////////////////////////
QVariant RectItem::itemChange(GraphicsItemChange _change,
const QVariant &_value)
{
if (_change == QGraphicsItem::ItemSelectedChange && this->scene())
{
this->SetHighlighted(_value.toBool());
}
else if (_change == QGraphicsItem::ItemScenePositionHasChanged
&& this->scene())
{
emit PosXChanged(this->scenePos().x());
emit PosYChanged(this->scenePos().y());
}
return QGraphicsItem::itemChange(_change, _value);
}
/////////////////////////////////////////////////
void RectItem::SetHighlighted(bool _highlighted)
{
if (_highlighted)
{
this->setZValue(this->ZValueSelected());
WallSegmentItem *wallItem = dynamic_cast<WallSegmentItem *>(
this->parentItem());
if (wallItem)
wallItem->setZValue(wallItem->ZValueSelected());
for (int i = 0; i < 8; ++i)
{
if (this->dataPtr->grabbers[i]->isEnabled())
this->dataPtr->grabbers[i]->installSceneEventFilter(this);
}
this->dataPtr->rotateHandle->installSceneEventFilter(this);
this->Set3dTransparency(0.0);
}
else
{
this->setZValue(this->ZValueIdle());
WallSegmentItem *wallItem = dynamic_cast<WallSegmentItem *>(
this->parentItem());
if (wallItem)
wallItem->setZValue(wallItem->ZValueIdle());
for (int i = 0; i < 8; ++i)
{
if (this->dataPtr->grabbers[i]->isEnabled())
this->dataPtr->grabbers[i]->removeSceneEventFilter(this);
}
this->dataPtr->rotateHandle->removeSceneEventFilter(this);
this->Set3dTransparency(0.4);
}
this->highlighted = _highlighted;
this->UpdateMeasures();
}
/////////////////////////////////////////////////
bool RectItem::sceneEventFilter(QGraphicsItem * _watched, QEvent *_event)
{
RotateHandle *rotateH = dynamic_cast<RotateHandle *>(_watched);
if (rotateH != NULL)
return this->RotateEventFilter(rotateH, _event);
GrabberHandle *grabber = dynamic_cast<GrabberHandle *>(_watched);
if (grabber != NULL && grabber->isEnabled())
return this->GrabberEventFilter(grabber, _event);
return false;
}
/////////////////////////////////////////////////
bool RectItem::RotateEventFilter(RotateHandle *_rotate, QEvent *_event)
{
QGraphicsSceneMouseEvent *mouseEvent =
dynamic_cast<QGraphicsSceneMouseEvent*>(_event);
switch (_event->type())
{
case QEvent::GraphicsSceneMousePress:
{
_rotate->SetMouseState(
static_cast<int>(QEvent::GraphicsSceneMousePress));
_rotate->SetMouseDownX(mouseEvent->pos().x());
_rotate->SetMouseDownY(mouseEvent->pos().y());
break;
}
case QEvent::GraphicsSceneMouseRelease:
{
_rotate->SetMouseState(
static_cast<int>(QEvent::GraphicsSceneMouseRelease));
break;
}
case QEvent::GraphicsSceneMouseMove:
{
_rotate->SetMouseState(static_cast<int>(QEvent::GraphicsSceneMouseMove));
break;
}
case QEvent::GraphicsSceneHoverEnter:
case QEvent::GraphicsSceneHoverMove:
{
// QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
QApplication::setOverrideCursor(BuildingEditorWidget::rotateCursor);
return true;
}
case QEvent::GraphicsSceneHoverLeave:
{
QApplication::restoreOverrideCursor();
return true;
}
default:
return false;
break;
}
if (!mouseEvent)
return false;
if (_rotate->MouseState()
== static_cast<int>(QEvent::GraphicsSceneMouseMove))
{
QPoint localCenter(this->drawingOriginX, this->drawingOriginY);
QPointF center = this->mapToScene(localCenter);
QPointF newPoint = mouseEvent->scenePos();
QLineF line(center.x(), center.y(), newPoint.x(), newPoint.y());
double angle = 0;
if (this->parentItem())
{
QPointF localCenterTop(this->drawingOriginX, this->drawingOriginY
+ this->drawingHeight);
QPointF centerTop = this->mapToScene(localCenterTop);
QLineF lineCenter(center.x(), center.y(), centerTop.x(), centerTop.y());
angle = -lineCenter.angleTo(line);
if (angle < 0)
angle += 360;
if (angle < 90 || angle > 270)
{
angle = 180;
this->SetRotation(this->Rotation() + angle);
if (this->AngleOnWall() < 90)
this->SetAngleOnWall(180);
else
this->SetAngleOnWall(0);
}
}
else
{
QLineF prevLine(center.x(), center.y(),
mouseEvent->lastScenePos().x(), mouseEvent->lastScenePos().y());
angle = -prevLine.angleTo(line);
this->SetRotation(this->Rotation() + angle);
}
}
return true;
}
/////////////////////////////////////////////////
bool RectItem::GrabberEventFilter(GrabberHandle *_grabber, QEvent *_event)
{
QGraphicsSceneMouseEvent *mouseEvent =
dynamic_cast<QGraphicsSceneMouseEvent*>(_event);
switch (_event->type())
{
case QEvent::GraphicsSceneMousePress:
{
_grabber->SetMouseState(
static_cast<int>(QEvent::GraphicsSceneMousePress));
_grabber->SetMouseDownX(mouseEvent->pos().x());
_grabber->SetMouseDownY(mouseEvent->pos().y());
break;
}
case QEvent::GraphicsSceneMouseRelease:
{
_grabber->SetMouseState(
static_cast<int>(QEvent::GraphicsSceneMouseRelease));
break;
}
case QEvent::GraphicsSceneMouseMove:
{
_grabber->SetMouseState(static_cast<int>(QEvent::GraphicsSceneMouseMove));
break;
}
case QEvent::GraphicsSceneHoverEnter:
case QEvent::GraphicsSceneHoverMove:
{
double angle = this->rotationAngle
- static_cast<int>(this->rotationAngle/360) * 360;
double range = 22.5;
if (angle < 0)
angle += 360;
if ((angle > (360 - range)) || (angle < range)
|| ((angle <= (180 + range)) && (angle > (180 - range))))
{
QApplication::setOverrideCursor(
QCursor(this->dataPtr->cursors[_grabber->Index() % 4]));
}
else if (((angle <= (360 - range)) && (angle > (270 + range)))
|| ((angle <= (180 - range)) && (angle > (90 + range))))
{
QApplication::setOverrideCursor(
QCursor(this->dataPtr->cursors[(_grabber->Index() + 3) % 4]));
}
else if (((angle <= (270 + range)) && (angle > (270 - range)))
|| ((angle <= (90 + range)) && (angle > (90 - range))))
{
QApplication::setOverrideCursor(
QCursor(this->dataPtr->cursors[(_grabber->Index() + 2) % 4]));
}
else
{
QApplication::setOverrideCursor(
QCursor(this->dataPtr->cursors[(_grabber->Index() + 1) % 4]));
}
return true;
}
case QEvent::GraphicsSceneHoverLeave:
{
QApplication::restoreOverrideCursor();
return true;
}
default:
return false;
}
if (!mouseEvent)
return false;
if (_grabber->MouseState()
== static_cast<int>(QEvent::GraphicsSceneMouseMove))
{
double xPos = mouseEvent->pos().x();
double yPos = mouseEvent->pos().y();
// depending on which grabber has been grabbed, we want to move the position
// of the item as it grows/shrinks accordingly. so we need to either add
// or subtract the offsets based on which grabber this is.
int xAxisSign = 0;
int yAxisSign = 0;
switch (_grabber->Index())
{
// corners
case 0:
{
xAxisSign = 1;
yAxisSign = 1;
break;
}
case 2:
{
xAxisSign = -1;
yAxisSign = 1;
break;
}
case 4:
{
xAxisSign = -1;
yAxisSign = -1;
break;
}
case 6:
{
xAxisSign = +1;
yAxisSign = -1;
break;
}
// edges
case 1:
{
xAxisSign = 0;
yAxisSign = 1;
break;
}
case 3:
{
xAxisSign = -1;
yAxisSign = 0;
break;
}
case 5:
{
xAxisSign = 0;
yAxisSign = -1;
break;
}
case 7:
{
xAxisSign = 1;
yAxisSign = 0;
break;
}
default:
break;
}
// if the mouse is being dragged, calculate a new size and also position
// for resizing the box
double xMoved = _grabber->MouseDownX() - xPos;
double yMoved = _grabber->MouseDownY() - yPos;
double newWidth = this->width + (xAxisSign * xMoved);
if (newWidth < 20)
newWidth = 20;
double newHeight = this->height + (yAxisSign * yMoved);
if (newHeight < 20)
newHeight = 20;
double deltaWidth = newWidth - this->width;
double deltaHeight = newHeight - this->height;
this->AdjustSize(deltaWidth, deltaHeight);
deltaWidth *= (-1);
deltaHeight *= (-1);
double angle = this->rotationAngle / 360.0 * (2 * M_PI);
double dx = 0;
double dy = 0;
auto currentPos = Conversions::Convert(this->pos());
switch (_grabber->Index())
{
// grabbers
case 0:
{
dx = sin(-angle) * deltaHeight/2;
dy = cos(-angle) * deltaHeight/2;
dx += cos(angle) * deltaWidth/2;
dy += sin(angle) * deltaWidth/2;
this->SetPosition(currentPos + ignition::math::Vector2d(dx, dy));
break;
}
case 2:
{
dx = sin(-angle) * deltaHeight/2;
dy = cos(-angle) * deltaHeight/2;
dx += -cos(angle) * deltaWidth/2;
dy += -sin(angle) * deltaWidth/2;
this->SetPosition(currentPos + ignition::math::Vector2d(dx, dy));
break;
}
case 4:
{
dx = -sin(-angle) * deltaHeight/2;
dy = -cos(-angle) * deltaHeight/2;
dx += -cos(angle) * deltaWidth/2;
dy += -sin(angle) * deltaWidth/2;
this->SetPosition(currentPos + ignition::math::Vector2d(dx, dy));
break;
}
case 6:
{
dx = -sin(-angle) * deltaHeight/2;
dy = -cos(-angle) * deltaHeight/2;
dx += cos(angle) * deltaWidth/2;
dy += sin(angle) * deltaWidth/2;
this->SetPosition(currentPos + ignition::math::Vector2d(dx, dy));
break;
}
// edges
case 1:
{
dx = sin(-angle) * deltaHeight/2;
dy = cos(-angle) * deltaHeight/2;
this->SetPosition(currentPos + ignition::math::Vector2d(dx, dy));
break;
}
case 3:
{
dx = cos(-angle) * deltaWidth/2;
dy = -sin(-angle) * deltaWidth/2;
this->SetPosition(currentPos - ignition::math::Vector2d(dx, dy));
if (this->parentItem())
{
WallSegmentItem *wallItem = dynamic_cast<WallSegmentItem *>(
this->parentItem());
if (wallItem)
{
if (this->AngleOnWall() < 90)
{
this->dataPtr->positionOnWall -= deltaWidth /
(2*wallItem->line().length());
}
else
{
this->dataPtr->positionOnWall += deltaWidth /
(2*wallItem->line().length());
}
}
}
break;
}
case 5:
{
dx = sin(-angle) * deltaHeight/2;
dy = cos(-angle) * deltaHeight/2;
this->SetPosition(currentPos - ignition::math::Vector2d(dx, dy));
break;
}
case 7:
{
dx = cos(angle) * deltaWidth/2;
dy = sin(angle) * deltaWidth/2;
this->SetPosition(currentPos + ignition::math::Vector2d(dx, dy));
if (this->parentItem())
{
WallSegmentItem *wallItem = dynamic_cast<WallSegmentItem *>(
this->parentItem());
if (wallItem)
{
if (this->AngleOnWall() < 90)
{
this->dataPtr->positionOnWall += deltaWidth /
(2*wallItem->line().length());
}
else
{
this->dataPtr->positionOnWall -= deltaWidth /
(2*wallItem->line().length());
}
}
}
break;
}
default:
break;
}
this->UpdateCornerPositions();
this->update();
}
return true;
}
/////////////////////////////////////////////////
void RectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *_event)
{
/// TODO: uncomment to enable snap to grid
/* this->location.setX( (static_cast<int>(this->location.x())
/ this->gridSpace) * this->gridSpace);
this->location.setY( (static_cast<int>(this->location.y())
/ this->gridSpace) * this->gridSpace);*/
this->dataPtr->mousePressPos = ignition::math::Vector2d::Zero;
_event->setAccepted(true);
}
/////////////////////////////////////////////////
void RectItem::mousePressEvent(QGraphicsSceneMouseEvent *_event)
{
// if (!this->isSelected())
// this->scene()->clearSelection();
// this->setSelected(true);
QApplication::setOverrideCursor(QCursor(Qt::SizeAllCursor));
this->dataPtr->mousePressPos =
Conversions::Convert(this->mapFromScene(_event->scenePos()));
_event->setAccepted(true);
}
/////////////////////////////////////////////////
void RectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *_event)
{
if (!this->isSelected())
return;
// QPointF delta = _event->scenePos() - _event->lastScenePos();
// this->SetPosition(this->scenePos() + delta);
// this->dataPtr->location += delta;
// this->SetPosition(this->dataPtr->location);
// keep track of mouse press pos for more accurate mouse movements than
// purely relying on mouse translations because we expect items to rotate
// arbitrary (snap to parent items) when dragged
QPointF trans = this->mapFromScene(_event->scenePos()) -
Conversions::Convert(this->dataPtr->mousePressPos);
QPointF rotatedTrans;
rotatedTrans.setX(cos(IGN_DTOR(this->rotationAngle))*-trans.x()
- sin(IGN_DTOR(this->rotationAngle))*-trans.y());
rotatedTrans.setY(sin(IGN_DTOR(this->rotationAngle))*-trans.x()
+ cos(IGN_DTOR(this->rotationAngle))*-trans.y());
this->SetPosition(Conversions::Convert(this->pos() - rotatedTrans));
}
/////////////////////////////////////////////////
void RectItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *_event)
{
_event->setAccepted(true);
}
/////////////////////////////////////////////////
void RectItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *_event)
{
if (!this->isSelected())
{
_event->ignore();
return;
}
QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
for (int i = 0; i < 8; ++i)
{
if (this->dataPtr->grabbers[i]->isEnabled())
this->dataPtr->grabbers[i]->removeSceneEventFilter(this);
}
this->dataPtr->rotateHandle->removeSceneEventFilter(this);
}
/////////////////////////////////////////////////
void RectItem::hoverMoveEvent(QGraphicsSceneHoverEvent *_event)
{
if (!this->isSelected())
{
_event->ignore();
return;
}
QApplication::setOverrideCursor(QCursor(Qt::SizeAllCursor));
}
/////////////////////////////////////////////////
void RectItem::hoverEnterEvent(QGraphicsSceneHoverEvent *_event)
{
if (!this->isSelected())
{
_event->ignore();
return;
}
QApplication::setOverrideCursor(QCursor(Qt::SizeAllCursor));
for (unsigned int i = 0; i < this->dataPtr->grabbers.size(); ++i)
{
if (this->dataPtr->grabbers[i]->isEnabled())
this->dataPtr->grabbers[i]->installSceneEventFilter(this);
}
this->dataPtr->rotateHandle->installSceneEventFilter(this);
}
/////////////////////////////////////////////////
void RectItem::UpdateCornerPositions()
{
int grabberWidth = (this->dataPtr->grabbers[0]->boundingRect().width())/2;
int grabberHeight = (this->dataPtr->grabbers[0]->boundingRect().height())/2;
this->dataPtr->grabbers[0]->setPos(
this->drawingOriginX - this->drawingWidth/2 - grabberWidth,
this->drawingOriginY - this->drawingHeight/2 - grabberHeight);
this->dataPtr->grabbers[2]->setPos(
this->drawingOriginX + this->drawingWidth/2 - grabberWidth,
this->drawingOriginY - this->drawingHeight/2 - grabberHeight);
this->dataPtr->grabbers[4]->setPos(
this->drawingOriginX + this->drawingWidth/2 - grabberWidth,
this->drawingOriginY + this->drawingHeight/2 - grabberHeight);
this->dataPtr->grabbers[6]->setPos(
this->drawingOriginX - this->drawingWidth/2 -grabberWidth,
this->drawingOriginY + this->drawingHeight/2 - grabberHeight);
this->dataPtr->grabbers[1]->setPos(
this->drawingOriginX - grabberWidth,
this->drawingOriginY - this->drawingHeight/2 - grabberHeight);
this->dataPtr->grabbers[3]->setPos(
this->drawingOriginX + this->drawingWidth/2 - grabberWidth,
this->drawingOriginY - grabberHeight);
this->dataPtr->grabbers[5]->setPos(
this->drawingOriginX - grabberWidth,
this->drawingOriginY + this->drawingHeight/2 - grabberHeight);
this->dataPtr->grabbers[7]->setPos(
this->drawingOriginX - this->drawingWidth/2 - grabberWidth,
this->drawingOriginY - grabberHeight);
this->dataPtr->rotateHandle->setPos(this->drawingOriginX,
this->drawingOriginY - this->drawingHeight/2);
this->SizeChanged();
this->setRect(this->boundingRect());
// this->setPolygon(QPolygonF(this->boundingRect()));
}
/////////////////////////////////////////////////
void RectItem::SetWidth(int _width)
{
this->width = _width;
this->drawingWidth = this->width;
this->UpdateCornerPositions();
this->update();
emit WidthChanged(this->drawingWidth);
}
/////////////////////////////////////////////////
void RectItem::SetHeight(int _height)
{
this->height = _height;
this->drawingHeight = this->height;
this->UpdateCornerPositions();
this->update();
emit DepthChanged(this->drawingHeight);
}
/////////////////////////////////////////////////
void RectItem::SetSize(const ignition::math::Vector2i &_size)
{
this->width = _size.X();
this->drawingWidth = this->width;
this->height = _size.Y();
this->drawingHeight = this->height;
this->UpdateCornerPositions();
this->update();
emit WidthChanged(this->drawingWidth);
emit DepthChanged(this->drawingHeight);
}
/////////////////////////////////////////////////
double RectItem::Width() const
{
return this->drawingWidth;
}
/////////////////////////////////////////////////
double RectItem::Height() const
{
return this->drawingHeight;
}
/////////////////////////////////////////////////
void RectItem::SetPositionOnWall(double _positionOnWall)
{
this->dataPtr->positionOnWall = _positionOnWall;
this->UpdateMeasures();
}
/////////////////////////////////////////////////
double RectItem::PositionOnWall() const
{
return this->dataPtr->positionOnWall;
}
/////////////////////////////////////////////////
void RectItem::SetAngleOnWall(double _angleOnWall)
{
this->dataPtr->angleOnWall = _angleOnWall;
this->UpdateMeasures();
}
/////////////////////////////////////////////////
double RectItem::AngleOnWall() const
{
return this->dataPtr->angleOnWall;
}
/////////////////////////////////////////////////
QRectF RectItem::boundingRect() const
{
return QRectF(-this->width/2, -this->height/2, this->width, this->height);
}
/////////////////////////////////////////////////
void RectItem::DrawBoundingBox(QPainter *_painter)
{
_painter->save();
QPen boundingBoxPen;
boundingBoxPen.setStyle(Qt::DashDotLine);
boundingBoxPen.setColor(Qt::darkGray);
boundingBoxPen.setCapStyle(Qt::RoundCap);
boundingBoxPen.setJoinStyle(Qt::RoundJoin);
_painter->setPen(boundingBoxPen);
_painter->setOpacity(0.8);
_painter->drawRect(this->boundingRect());
_painter->restore();
}
/////////////////////////////////////////////////
ignition::math::Vector3d RectItem::Size() const
{
return ignition::math::Vector3d(this->width, this->height, 0);
}
/////////////////////////////////////////////////
ignition::math::Vector3d RectItem::ScenePosition() const
{
return ignition::math::Vector3d(
this->scenePos().x(), this->scenePos().y(), 0);
}
/////////////////////////////////////////////////
double RectItem::SceneRotation() const
{
return this->rotationAngle;
}
/////////////////////////////////////////////////
void RectItem::paint(QPainter *_painter, const QStyleOptionGraphicsItem *,
QWidget *)
{
_painter->save();
QPointF topLeft(this->drawingOriginX - this->drawingWidth/2,
this->drawingOriginY - this->drawingHeight/2);
QPointF topRight(this->drawingOriginX + this->drawingWidth/2,
this->drawingOriginY - this->drawingHeight/2);
QPointF bottomLeft(this->drawingOriginX - this->drawingWidth/2,
this->drawingOriginY + this->drawingHeight/2);
QPointF bottomRight(this->drawingOriginX + this->drawingWidth/2,
this->drawingOriginY + this->drawingHeight/2);
QPen rectPen;
rectPen.setStyle(Qt::SolidLine);
rectPen.setColor(Conversions::Convert(this->borderColor));
_painter->setPen(rectPen);
_painter->drawLine(topLeft, topRight);
_painter->drawLine(topRight, bottomRight);
_painter->drawLine(bottomRight, bottomLeft);
_painter->drawLine(bottomLeft, topLeft);
_painter->restore();
}
/////////////////////////////////////////////////
void RectItem::mouseMoveEvent(QGraphicsSceneDragDropEvent *_event)
{
_event->setAccepted(false);
}
/////////////////////////////////////////////////
void RectItem::mousePressEvent(QGraphicsSceneDragDropEvent *_event)
{
_event->setAccepted(false);
}
/////////////////////////////////////////////////
void RectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *_event)
{
QMenu menu;
menu.addAction(this->openInspectorAct);
menu.addAction(this->deleteItemAct);
menu.exec(_event->screenPos());
_event->accept();
}
/////////////////////////////////////////////////
void RectItem::OnOpenInspector()
{
}
/////////////////////////////////////////////////
void RectItem::OnDeleteItem()
{
}
/////////////////////////////////////////////////
void RectItem::SetPosition(const ignition::math::Vector2d &_pos)
{
this->SetPosition(_pos.X(), _pos.Y());
}
/////////////////////////////////////////////////
void RectItem::SetPosition(double _x, double _y)
{
this->setPos(_x, _y);
// emit posXChanged(_x);
// emit posYChanged(_y);
}
/////////////////////////////////////////////////
void RectItem::SetRotation(double _angle)
{
this->rotate(_angle - this->rotationAngle);
this->rotationAngle = _angle;
emit YawChanged(this->rotationAngle);
}
/////////////////////////////////////////////////
double RectItem::Rotation() const
{
return this->rotationAngle;
}
/////////////////////////////////////////////////
void RectItem::SizeChanged()
{
emit DepthChanged(this->drawingHeight);
emit WidthChanged(this->drawingWidth);
this->UpdateMeasures();
}
/////////////////////////////////////////////////
void RectItem::SetResizeFlag(unsigned int _flag)
{
if (this->dataPtr->resizeFlag == _flag)
return;
this->dataPtr->resizeFlag = _flag;
for (int i = 0; i < 8; ++i)
this->dataPtr->grabbers[i]->setEnabled(false);
if (this->dataPtr->resizeFlag & ITEM_WIDTH)
{
this->dataPtr->grabbers[3]->setEnabled(true);
this->dataPtr->grabbers[7]->setEnabled(true);
}
if (this->dataPtr->resizeFlag & ITEM_HEIGHT)
{
this->dataPtr->grabbers[1]->setEnabled(true);
this->dataPtr->grabbers[5]->setEnabled(true);
}
if ((this->dataPtr->resizeFlag & ITEM_WIDTH) &&
(this->dataPtr->resizeFlag & ITEM_HEIGHT))
{
this->dataPtr->grabbers[0]->setEnabled(true);
this->dataPtr->grabbers[2]->setEnabled(true);
this->dataPtr->grabbers[4]->setEnabled(true);
this->dataPtr->grabbers[6]->setEnabled(true);
}
}
/////////////////////////////////////////////////
void RectItem::UpdateMeasures()
{
// Only windows and doors can have a wall as parent
WallSegmentItem *wallItem = dynamic_cast<WallSegmentItem *>(
this->parentItem());
if (wallItem == NULL)
{
for (unsigned int i = 0; i < this->measures.size(); ++i)
{
this->measures[i]->setVisible(false);
}
return;
}
if (this->measures.empty())
{
this->measures.push_back(new MeasureItem(ignition::math::Vector2d(0, 0),
ignition::math::Vector2d(0, 1)));
this->measures.push_back(new MeasureItem(ignition::math::Vector2d(0, 0),
ignition::math::Vector2d(0, 1)));
this->measures[0]->setVisible(false);
this->measures[1]->setVisible(false);
}
this->measures[0]->setParentItem(wallItem);
this->measures[1]->setParentItem(wallItem);
this->measures[0]->setVisible(this->highlighted);
this->measures[1]->setVisible(this->highlighted);
if (this->highlighted)
{
// Half wall thickness
double t = wallItem->Thickness()/2;
// Distance in px between wall line and measure line
double d = 20 + t;
// Half the RectItem's length
double w = this->drawingWidth/2;
// This item's angle on the scene
double angle = IGN_DTOR(this->rotationAngle);
// Free vector of t on wall direction, for the extremes
ignition::math::Vector2d tVec(t*qCos(angle), t*qSin(angle));
// Free vector of d perpendicular to the wall
ignition::math::Vector2d dVec(d*cos(angle+M_PI/2.0),
d*sin(angle+M_PI/2.0));
auto p1wall = wallItem->StartPoint();
auto p2wall = wallItem->EndPoint();
ignition::math::Vector2d p1rect(this->scenePos().x()-w*qCos(angle),
this->scenePos().y()-w*qSin(angle));
ignition::math::Vector2d p2rect(this->scenePos().x()+w*qCos(angle),
this->scenePos().y()+w*qSin(angle));
auto extreme1 = p1wall;
auto extreme2 = p2wall;
// Swap extremes if item is flipped on wall
if (this->AngleOnWall() > 90)
{
extreme1 = p2wall;
extreme2 = p1wall;
}
// Measure 0, from extreme 1 to RectItem's start point
this->measures[0]->SetStartPoint(extreme1 - tVec - dVec);
this->measures[0]->SetEndPoint(p1rect - dVec);
// Measure 1, from RectItem's end point to extreme 2
this->measures[1]->SetStartPoint(p2rect - dVec);
this->measures[1]->SetEndPoint(extreme2 + tVec - dVec);
this->measures[0]->SetValue(
(this->measures[0]->line().length())*this->itemScale);
this->measures[1]->SetValue(
(this->measures[1]->line().length())*this->itemScale);
}
}
/////////////////////////////////////////////////
void RectItem::DetachFromParent()
{
this->setParentItem(NULL);
for (unsigned int i = 0; i < this->measures.size(); i++)
this->measures[i]->setParentItem(NULL);
}