38 #include <QFontMetrics>
50 #include "boost/bind.hpp"
51 #include "libQtSignalAdapters/Qt2Func.h"
52 #include "libQtSignalAdapters/ConnectionFactories.h"
69 QRect rect = QFontMetrics(this->font()).boundingRect(text);
70 QSize s(rect.width()*1.0+5, 4*rect.height()*1.2+5);
90 BaseWidget(parent,
"Transform3DWidget",
"Transform 3D")
92 this->setToolTip(
"Display and manipulate an affine (rotation+translation) matrix");
94 mBlockChanges =
false;
96 QVBoxLayout* toptopLayout =
new QVBoxLayout(
this);
97 toptopLayout->setMargin(4);
98 QHBoxLayout* mLayout =
new QHBoxLayout;
99 mLayout->setMargin(0);
100 toptopLayout->addLayout(mLayout);
103 mTextEdit->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Maximum);
104 mTextEdit->setLineWrapMode(QTextEdit::NoWrap);
105 mTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
106 mTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
107 connect(mTextEdit, SIGNAL(textChanged()),
this, SLOT(textEditChangedSlot()));
109 mLayout->addWidget(mTextEdit, 1);
111 QVBoxLayout* buttonLayout =
new QVBoxLayout;
112 mLayout->addLayout(buttonLayout);
113 buttonLayout->setMargin(0);
116 QIcon(
":/icons/open_icon_library/system-run-5.png"),
118 "Toggle Edit Matrix",
119 SLOT(toggleEditSlot()),
121 mEditAction->setCheckable(
true);
124 QIcon(
":/icons/matrix_inverse.png"),
126 "Toggle Invert Matrix",
127 SLOT(toggleInvertSlot()),
129 mInvertAction->setCheckable(
true);
130 mInvertAction->setChecked(
false);
131 this->updateInvertAction();
135 aGroupBox =
new QFrame(
this);
136 QVBoxLayout* aLayout =
new QVBoxLayout;
137 aGroupBox->setLayout(aLayout);
138 aGroupBox->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
139 aGroupBox->setLineWidth(3);
140 aLayout->setMargin(4);
141 toptopLayout->addWidget(aGroupBox);
143 this->addAngleControls(
"xAngle",
"X Angle", 0, aLayout);
144 this->addAngleControls(
"yAngle",
"Y Angle", 1, aLayout);
145 this->addAngleControls(
"zAngle",
"Z Angle", 2, aLayout);
147 tGroupBox =
new QFrame(
this);
148 QVBoxLayout* tLayout =
new QVBoxLayout;
149 tGroupBox->setLayout(tLayout);
150 tGroupBox->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
151 tGroupBox->setLineWidth(3);
152 tLayout->setMargin(4);
153 toptopLayout->addWidget(tGroupBox);
155 this->addTranslationControls(
"xTranslation",
"X", 0, tLayout);
156 this->addTranslationControls(
"yTranslation",
"Y", 1, tLayout);
157 this->addTranslationControls(
"zTranslation",
"Z", 2, tLayout);
159 this->setMatrixInternal(Transform3D::Identity());
161 toptopLayout->addStretch();
166 void Transform3DWidget::textEditChangedSlot()
169 Transform3D M = Transform3D::fromString(mTextEdit->toPlainText(), &ok);
173 if (
similar(M, this->getMatrixInternal()))
176 this->setMatrixInternal(M);
179 void Transform3DWidget::toggleEditSlot()
181 bool visible = tGroupBox->isVisible();
186 void Transform3DWidget::toggleInvertSlot()
194 void Transform3DWidget::updateInvertAction()
196 if (mInvertAction->isChecked())
198 this->setActionText(mInvertAction,
"Inverted Matrix",
"The matrix is shown inverted");
202 this->setActionText(mInvertAction,
"Noninverted Matrix",
"The matrix is shown as is. Press to show inverted");
206 void Transform3DWidget::setActionText(QAction* action, QString text, QString tip)
210 action->setText(text);
211 action->setStatusTip(tip);
212 action->setWhatsThis(tip);
213 action->setToolTip(tip);
218 mTextEdit->setReadOnly(!edit);
219 aGroupBox->setVisible(edit);
220 tGroupBox->setVisible(edit);
223 void Transform3DWidget::addAngleControls(QString uid, QString name,
int index, QVBoxLayout* layout)
225 QHBoxLayout* hLayout =
new QHBoxLayout;
228 connect(adapter.get(), SIGNAL(
changed()),
this, SLOT(changedSlot()));
229 adapter->setInternal2Display(180/
M_PI);
232 QSize mMinBarSize = QSize(20,20);
235 hLayout->addWidget(pad);
238 QtSignalAdapters::connect1<void(QPointF)>(pad, SIGNAL(mouseMoved(QPointF)),
239 boost::bind(&Transform3DWidget::rotateSlot,
this, _1, index));
241 layout->addLayout(hLayout);
242 mAngleAdapter[index] = adapter;
245 void Transform3DWidget::addTranslationControls(QString uid, QString name,
int index, QVBoxLayout* layout)
247 QHBoxLayout* hLayout =
new QHBoxLayout;
250 connect(adapter.get(), SIGNAL(
changed()),
this, SLOT(changedSlot()));
251 adapter->setInternal2Display(1.0);
252 hLayout->addWidget(
new SpinBoxGroupWidget(
this, adapter));
254 QSize mMinBarSize = QSize(20,20);
255 MousePadWidget* pad =
new MousePadWidget(
this, mMinBarSize);
256 pad->setFixedYPos(
true);
257 hLayout->addWidget(pad);
260 QtSignalAdapters::connect1<void(QPointF)>(pad, SIGNAL(mouseMoved(QPointF)),
261 boost::bind(&Transform3DWidget::translateSlot,
this, _1, index));
263 layout->addLayout(hLayout);
264 mTranslationAdapter[index] = adapter;
267 void Transform3DWidget::rotateSlot(QPointF delta,
int index)
269 double scale = M_PI_2;
270 double factor = scale * delta.x();
271 double current = mAngleAdapter[index]->getValue();
272 mAngleAdapter[index]->setValue(current + factor);
275 void Transform3DWidget::translateSlot(QPointF delta,
int index)
278 double factor = scale * delta.x();
279 double current = mTranslationAdapter[index]->getValue();
280 mTranslationAdapter[index]->setValue(current + factor);
290 this->setMatrixInternal(this->convertToFromExternal(M));
295 return this->convertToFromExternal(this->getMatrixInternal());
300 if (mInvertAction->isChecked())
310 void Transform3DWidget::setMatrixInternal(
const Transform3D& M)
312 mDecomposition.
reset(M);
317 Transform3D Transform3DWidget::getMatrixInternal()
const
325 void Transform3DWidget::changedSlot()
327 if (recursive || mBlockChanges)
330 Vector3D xyz(mAngleAdapter[0]->getValue(),mAngleAdapter[1]->getValue(),mAngleAdapter[2]->getValue());
333 Vector3D t(mTranslationAdapter[0]->getValue(),mTranslationAdapter[1]->getValue(),mTranslationAdapter[2]->getValue());
346 double wrapAngle(
double angle)
348 angle = fmod(angle,
M_PI * 2);
361 mTextEdit->blockSignals(
true);
362 int textPos = mTextEdit->textCursor().position();
363 mTextEdit->setText(M);
364 QTextCursor cursor = mTextEdit->textCursor();
365 cursor.setPosition(textPos);
366 mTextEdit->setTextCursor(cursor);
367 mTextEdit->blockSignals(
false);
371 mBlockChanges =
true;
373 mAngleAdapter[0]->setValue(wrapAngle(xyz[0]));
374 mAngleAdapter[1]->setValue(wrapAngle(xyz[1]));
375 mAngleAdapter[2]->setValue(wrapAngle(xyz[2]));
378 mTranslationAdapter[0]->setValue(t[0]);
379 mTranslationAdapter[1]->setValue(t[1]);
380 mTranslationAdapter[2]->setValue(t[2]);
382 this->updateInvertAction();
384 mBlockChanges =
false;
QString qstring_cast(const T &val)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
Utility class for describing a bounded numeric range.
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
MatrixTextEdit(QWidget *parent=NULL)
Transform3D createTransformTranslate(const Vector3D &translation)
boost::shared_ptr< class DoubleProperty > DoublePropertyPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
QSize minimumSizeHint() const
static DoublePropertyPtr initialize(const QString &uid, QString name, QString help, double value, DoubleRange range, int decimals, QDomNode root=QDomNode())
Transform3D createTransformRotateZ(const double angle)
Transform3D createTransformRotateX(const double angle)