00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025 #include <QDialogButtonBox>
00026 #include <QSignalMapper>
00027
00028 #include "Transform.h"
00029 #include "Selection.h"
00030 #include "ViewProvider.h"
00031 #include "ui_Placement.h"
00032 #include "Application.h"
00033 #include "Document.h"
00034 #include "WaitCursor.h"
00035 #include <App/PropertyGeo.h>
00036 #include <App/DocumentObject.h>
00037
00038 using namespace Gui::Dialog;
00039
00040 namespace Gui { namespace Dialog {
00041 class find_geometry_data
00042 {
00043 public:
00044 bool operator () (const std::pair<std::string, App::Property*>& elem) const
00045 {
00046 if (elem.first == "Points") {
00047 return elem.second->isDerivedFrom
00048 (Base::Type::fromName("Points::PropertyPointKernel"));
00049 }
00050 else if (elem.first == "Mesh") {
00051 return elem.second->isDerivedFrom
00052 (Base::Type::fromName("Mesh::PropertyMeshKernel"));
00053 }
00054 else if (elem.first == "Shape") {
00055 return elem.second->isDerivedFrom
00056 (Base::Type::fromName("Part::PropertyPartShape"));
00057 }
00058
00059
00060 return elem.second->isDerivedFrom
00061 (Base::Type::fromName("App::PropertyGeometry"));
00062 }
00063 };
00064 class find_placement
00065 {
00066 public:
00067 bool operator () (const std::pair<std::string, App::Property*>& elem) const
00068 {
00069 if (elem.first == "Placement") {
00070 return elem.second->isDerivedFrom
00071 (Base::Type::fromName("App::PropertyPlacement"));
00072 }
00073
00074 return false;
00075 }
00076 };
00077 }
00078 }
00079
00080
00081
00082 TransformStrategy::TransformStrategy()
00083 {
00084 }
00085
00086 TransformStrategy::~TransformStrategy()
00087 {
00088 }
00089
00090 Base::Vector3d TransformStrategy::getRotationCenter() const
00091 {
00092
00093
00094 std::set<App::DocumentObject*> objects = transformObjects();
00095 if (!objects.empty()) {
00096 Base::BoundBox3d bbox;
00097 bool first=true;
00098 for (std::set<App::DocumentObject*>::const_iterator it=objects.begin();it!=objects.end();++it) {
00099 std::map<std::string,App::Property*> props;
00100 (*it)->getPropertyMap(props);
00101
00102 std::map<std::string,App::Property*>::iterator jt;
00103 jt = std::find_if(props.begin(), props.end(), find_geometry_data());
00104 if (jt != props.end()) {
00105 if (first)
00106 bbox = (static_cast<App::PropertyGeometry*>(jt->second)->getBoundingBox());
00107 else
00108 bbox.Add(static_cast<App::PropertyGeometry*>(jt->second)->getBoundingBox());
00109 first = false;
00110 }
00111 }
00112
00113 return Base::Vector3d((bbox.MinX+bbox.MaxX)/2,
00114 (bbox.MinY+bbox.MaxY)/2,
00115 (bbox.MinZ+bbox.MaxZ)/2);
00116 }
00117
00118 return Base::Vector3d();
00119 }
00120
00121 void TransformStrategy::commitTransform(const Base::Matrix4D& mat)
00122 {
00123 std::set<App::DocumentObject*> objects = transformObjects();
00124 Gui::Document* doc = Gui::Application::Instance->activeDocument();
00125 if (doc) {
00126 doc->openCommand("Transform");
00127 for (std::set<App::DocumentObject*>::iterator it=objects.begin();it!=objects.end();++it) {
00128 acceptDataTransform(mat, *it);
00129 }
00130 doc->commitCommand();
00131 }
00132 }
00133
00134 void TransformStrategy::acceptDataTransform(const Base::Matrix4D& mat, App::DocumentObject* obj)
00135 {
00136 Gui::Document* doc = Gui::Application::Instance->getDocument(obj->getDocument());
00137 std::map<std::string,App::Property*> props;
00138 obj->getPropertyMap(props);
00139
00140 std::map<std::string,App::Property*>::iterator jt;
00141 jt = std::find_if(props.begin(), props.end(), find_placement());
00142 if (jt != props.end()) {
00143 Base::Placement local = static_cast<App::PropertyPlacement*>(jt->second)->getValue();
00144 Gui::ViewProvider* vp = doc->getViewProvider(obj);
00145 if (vp) vp->setTransformation(local.toMatrix());
00146 }
00147 else {
00148
00149 Gui::ViewProvider* vp = doc->getViewProvider(obj);
00150 if (vp) vp->setTransformation(Base::Matrix4D());
00151 }
00152
00153
00154 jt = std::find_if(props.begin(), props.end(), find_geometry_data());
00155 if (jt != props.end()) {
00156 static_cast<App::PropertyGeometry*>(jt->second)->transformGeometry(mat);
00157 }
00158 }
00159
00160 void TransformStrategy::applyTransform(const Base::Placement& plm)
00161 {
00162 std::set<App::DocumentObject*> objects = transformObjects();
00163 for (std::set<App::DocumentObject*>::iterator it=objects.begin();it!=objects.end();++it) {
00164 applyViewTransform(plm, *it);
00165 }
00166 }
00167
00168 void TransformStrategy::resetTransform()
00169 {
00170 std::set<App::DocumentObject*> objects = transformObjects();
00171 for (std::set<App::DocumentObject*>::iterator it=objects.begin();it!=objects.end();++it) {
00172 resetViewTransform(*it);
00173 }
00174 }
00175
00176 void TransformStrategy::applyViewTransform(const Base::Placement& plm, App::DocumentObject* obj)
00177 {
00178 Gui::Document* doc = Gui::Application::Instance->getDocument(obj->getDocument());
00179 std::map<std::string,App::Property*> props;
00180 obj->getPropertyMap(props);
00181
00182 std::map<std::string,App::Property*>::iterator jt;
00183 jt = std::find_if(props.begin(), props.end(), find_placement());
00184 if (jt != props.end()) {
00185 Base::Placement local = static_cast<App::PropertyPlacement*>(jt->second)->getValue();
00186 local *= plm;
00187 Gui::ViewProvider* vp = doc->getViewProvider(obj);
00188 if (vp) vp->setTransformation(local.toMatrix());
00189 }
00190 else {
00191
00192 Gui::ViewProvider* vp = doc->getViewProvider(obj);
00193 if (vp) vp->setTransformation(plm.toMatrix());
00194 }
00195 }
00196
00197 void TransformStrategy::resetViewTransform(App::DocumentObject* obj)
00198 {
00199 Gui::Document* doc = Gui::Application::Instance->getDocument(obj->getDocument());
00200 std::map<std::string,App::Property*> props;
00201 obj->getPropertyMap(props);
00202
00203 std::map<std::string,App::Property*>::iterator jt;
00204 jt = std::find_if(props.begin(), props.end(), find_placement());
00205 if (jt != props.end()) {
00206 Base::Placement local = static_cast<App::PropertyPlacement*>(jt->second)->getValue();
00207 Gui::ViewProvider* vp = doc->getViewProvider(obj);
00208 if (vp) vp->setTransformation(local.toMatrix());
00209 }
00210 else {
00211
00212 Gui::ViewProvider* vp = doc->getViewProvider(obj);
00213 if (vp) vp->setTransformation(Base::Matrix4D());
00214 }
00215 }
00216
00217
00218
00219 DefaultTransformStrategy::DefaultTransformStrategy(QWidget* w) : widget(w)
00220 {
00221 Gui::SelectionChanges mod;
00222 mod.Type = Gui::SelectionChanges::SetSelection;
00223 onSelectionChanged(mod);
00224 }
00225
00226 DefaultTransformStrategy::~DefaultTransformStrategy()
00227 {
00228 }
00229
00230 std::set<App::DocumentObject*> DefaultTransformStrategy::transformObjects() const
00231 {
00232 return selection;
00233 }
00234
00235 void DefaultTransformStrategy::onSelectionChanged(const Gui::SelectionChanges& msg)
00236 {
00237 if (msg.Type == SelectionChanges::SetPreselect ||
00238 msg.Type == SelectionChanges::RmvPreselect)
00239 return;
00240 if (msg.Type == SelectionChanges::ClrSelection) {
00241 widget->setDisabled(true);
00242 for (std::set<App::DocumentObject*>::iterator it = selection.begin();
00243 it != selection.end(); ++it)
00244 resetViewTransform(*it);
00245 selection.clear();
00246 return;
00247 }
00248
00249 std::set<App::DocumentObject*> update_selection;
00250 std::vector<App::DocumentObject*> sel = Gui::Selection().getObjectsOfType
00251 (App::DocumentObject::getClassTypeId());
00252 for (std::vector<App::DocumentObject*>::iterator it=sel.begin();it!=sel.end();++it) {
00253 std::map<std::string,App::Property*> props;
00254 (*it)->getPropertyMap(props);
00255
00256 std::map<std::string,App::Property*>::iterator jt;
00257 jt = std::find_if(props.begin(), props.end(), find_geometry_data());
00258 if (jt != props.end()) {
00259 update_selection.insert(*it);
00260 }
00261 }
00262
00263
00264
00265
00266
00267 std::set<App::DocumentObject*> filter;
00268 for (std::set<App::DocumentObject*>::iterator it=update_selection.begin();
00269 it!=update_selection.end();++it) {
00270 std::vector<App::DocumentObject*> deps = (*it)->getOutList();
00271 std::vector<App::DocumentObject*>::iterator jt;
00272 for (jt = deps.begin(); jt != deps.end(); ++jt) {
00273 if (update_selection.find(*jt) != update_selection.end()) {
00274 filter.insert(*it);
00275 break;
00276 }
00277 }
00278 }
00279
00280 if (!filter.empty()) {
00281 std::set<App::DocumentObject*> diff;
00282 std::insert_iterator< std::set<App::DocumentObject*> > biit(diff, diff.begin());
00283 std::set_difference(update_selection.begin(), update_selection.end(),
00284 filter.begin(), filter.end(), biit);
00285 update_selection = diff;
00286 }
00287
00288
00289 std::vector<App::DocumentObject*> diff;
00290 std::back_insert_iterator< std::vector<App::DocumentObject*> > biit(diff);
00291 std::set_difference(selection.begin(), selection.end(),
00292 update_selection.begin(), update_selection.end(), biit);
00293 for (std::vector<App::DocumentObject*>::iterator it = diff.begin(); it != diff.end(); ++it)
00294 resetViewTransform(*it);
00295 selection = update_selection;
00296
00297 widget->setDisabled(selection.empty());
00298 }
00299
00300
00301
00302
00303
00304 Transform::Transform(QWidget* parent, Qt::WFlags fl)
00305 : Gui::LocationDialog(parent, fl), strategy(0)
00306 {
00307 ui = new Ui_TransformComp(this);
00308 ui->resetButton->hide();
00309 ui->applyPlacementChange->hide();
00310 ui->applyIncrementalPlacement->hide();
00311
00312 ui->angle->setSuffix(QString::fromUtf8(" \xc2\xb0"));
00313 ui->yawAngle->setSuffix(QString::fromUtf8(" \xc2\xb0"));
00314 ui->pitchAngle->setSuffix(QString::fromUtf8(" \xc2\xb0"));
00315 ui->rollAngle->setSuffix(QString::fromUtf8(" \xc2\xb0"));
00316
00317 ui->closeButton->setText(tr("Cancel"));
00318 this->setWindowTitle(tr("Transform"));
00319
00320
00321 QSignalMapper* signalMapper = new QSignalMapper(this);
00322 connect(this, SIGNAL(directionChanged()), signalMapper, SLOT(map()));
00323 signalMapper->setMapping(this, 0);
00324
00325 int id = 1;
00326 QList<QDoubleSpinBox*> sb = this->findChildren<QDoubleSpinBox*>();
00327 for (QList<QDoubleSpinBox*>::iterator it = sb.begin(); it != sb.end(); ++it) {
00328 connect(*it, SIGNAL(valueChanged(double)), signalMapper, SLOT(map()));
00329 signalMapper->setMapping(*it, id++);
00330 }
00331
00332 connect(signalMapper, SIGNAL(mapped(int)),
00333 this, SLOT(onTransformChanged(int)));
00334
00335 setTransformStrategy(new DefaultTransformStrategy(this));
00336 }
00337
00338 Transform::~Transform()
00339 {
00340 delete ui;
00341 delete strategy;
00342 }
00343
00344 void Transform::setTransformStrategy(TransformStrategy* ts)
00345 {
00346 if (!ts || ts == strategy)
00347 return;
00348 if (strategy)
00349 delete strategy;
00350 strategy = ts;
00351 Base::Vector3d cnt = strategy->getRotationCenter();
00352 ui->xCnt->setValue(cnt.x);
00353 ui->yCnt->setValue(cnt.y);
00354 ui->zCnt->setValue(cnt.z);
00355 this->setDisabled(strategy->transformObjects().empty());
00356 }
00357
00358 void Transform::showStandardButtons(bool b)
00359 {
00360 ui->closeButton->setVisible(b);
00361 ui->oKButton->setVisible(b);
00362 ui->applyButton->setVisible(b);
00363 }
00364
00365 void Transform::onTransformChanged(int)
00366 {
00367 Base::Placement plm = this->getPlacementData();
00368 strategy->applyTransform(plm);
00369 }
00370
00371 void Transform::accept()
00372 {
00373 on_applyButton_clicked();
00374 QDialog::accept();
00375 }
00376
00377 void Transform::reject()
00378 {
00379 strategy->resetTransform();
00380 QDialog::reject();
00381 }
00382
00383 void Transform::on_applyButton_clicked()
00384 {
00385 Gui::WaitCursor wc;
00386 Base::Placement plm = this->getPlacementData();
00387 Base::Matrix4D mat = plm.toMatrix();
00388 strategy->commitTransform(mat);
00389
00390
00391 QList<QDoubleSpinBox*> sb = this->findChildren<QDoubleSpinBox*>();
00392 for (QList<QDoubleSpinBox*>::iterator it = sb.begin(); it != sb.end(); ++it) {
00393 (*it)->blockSignals(true);
00394 (*it)->setValue(0.0);
00395 (*it)->blockSignals(false);
00396 }
00397
00398 Base::Vector3d cnt = strategy->getRotationCenter();
00399 ui->xCnt->setValue(cnt.x);
00400 ui->yCnt->setValue(cnt.y);
00401 ui->zCnt->setValue(cnt.z);
00402 }
00403
00404 void Transform::directionActivated(int index)
00405 {
00406 if (ui->directionActivated(this, index)) {
00407 directionChanged();
00408 }
00409 }
00410
00411 Base::Vector3f Transform::getDirection() const
00412 {
00413 return ui->getDirection();
00414 }
00415
00416 Base::Placement Transform::getPlacementData() const
00417 {
00418 int index = ui->rotationInput->currentIndex();
00419 Base::Rotation rot;
00420 Base::Vector3d pos;
00421 Base::Vector3d cnt;
00422
00423 pos = Base::Vector3d(ui->xPos->value(),ui->yPos->value(),ui->zPos->value());
00424 cnt = Base::Vector3d(ui->xCnt->value(),ui->yCnt->value(),ui->zCnt->value());
00425
00426 if (index == 0) {
00427 Base::Vector3f dir = getDirection();
00428 rot.setValue(Base::Vector3d(dir.x,dir.y,dir.z),ui->angle->value()*D_PI/180.0);
00429 }
00430 else if (index == 1) {
00431 rot.setYawPitchRoll(
00432 ui->yawAngle->value(),
00433 ui->pitchAngle->value(),
00434 ui->rollAngle->value());
00435 }
00436
00437 Base::Placement p(pos, rot, cnt);
00438 return p;
00439 }
00440
00441 void Transform::changeEvent(QEvent *e)
00442 {
00443 if (e->type() == QEvent::LanguageChange) {
00444 ui->retranslate(this);
00445 ui->closeButton->setText(tr("Cancel"));
00446 this->setWindowTitle(tr("Transform"));
00447 }
00448 else {
00449 QDialog::changeEvent(e);
00450 }
00451 }
00452
00453
00454
00455 TaskTransform::TaskTransform()
00456 {
00457 this->setButtonPosition(TaskTransform::South);
00458 dialog = new Transform();
00459 dialog->showStandardButtons(false);
00460 taskbox = new Gui::TaskView::TaskBox(QPixmap(), dialog->windowTitle(), true, 0);
00461 taskbox->groupLayout()->addWidget(dialog);
00462 Content.push_back(taskbox);
00463 }
00464
00465 TaskTransform::~TaskTransform()
00466 {
00467
00468 }
00469
00470 void TaskTransform::setTransformStrategy(TransformStrategy* ts)
00471 {
00472 dialog->setTransformStrategy(ts);
00473 }
00474
00475 bool TaskTransform::accept()
00476 {
00477 dialog->accept();
00478 return (dialog->result() == QDialog::Accepted);
00479 }
00480
00481 bool TaskTransform::reject()
00482 {
00483 dialog->reject();
00484 return (dialog->result() == QDialog::Rejected);
00485 }
00486
00487 void TaskTransform::clicked(int id)
00488 {
00489 if (id == QDialogButtonBox::Apply) {
00490 dialog->on_applyButton_clicked();
00491 }
00492 }
00493
00494 #include "moc_Transform.cpp"