/*************************************************************************** * Copyright (c) 2009 Juergen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library 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 Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include #endif #include "TaskAssemblyConstraints.h" #include #include #include #include #include #include #include #include #include #include #include using namespace AssemblyGui; using namespace Gui::TaskView; extern Assembly::Item* ActiveAsmObject; TaskAssemblyConstraints::TaskAssemblyConstraints(ViewProviderConstraint* vp) : TaskBox(Gui::BitmapFactory().pixmap("document-new"),tr("Constraints"),true, 0), view(vp) { // we need a separate container widget to add all controls to proxy = new QWidget(this); ui = new Ui::TaskAssemblyConstraints(); ui->setupUi(proxy); this->groupLayout()->addWidget(proxy); //initialy hide the value and orientation field ui->value_widget->hide(); ui->orientation_widget->hide(); //set all basic values Assembly::ItemAssembly* ass = NULL; Assembly::Constraint* obj = dynamic_cast(vp->getObject()); if(obj->First.getValue()) { QString str; str = QString::fromAscii(obj->First.getValue()->getNameInDocument()) + QString::fromAscii(".") + QString::fromStdString(obj->First.getSubValues().front()); ui->first_geom->setText(str); ass = dynamic_cast(obj->First.getValue())->getParentAssembly(); }; if(obj->Second.getValue()) { QString str; str = QString::fromAscii(obj->Second.getValue()->getNameInDocument()) + QString::fromAscii(".") + QString::fromStdString(obj->Second.getSubValues().front()); ui->second_geom->setText(str); if(!ass) ass = dynamic_cast(obj->Second.getValue())->getParentAssembly(); }; if(ass) ass->execute(); //get the individual constraint settings ui->value->setValue(obj->Value.getValue()); setOrientation(dcm::Direction(obj->Orientation.getValue())); setSolutionSpace(dcm::SolutionSpace(obj->SolutionSpace.getValue())); int v = obj->Type.getValue(); if(v==0) ui->fix->setChecked(true); if(v==1) ui->distance->setChecked(true); if(v==2) ui->orientation->setChecked(true); if(v==3) ui->angle->setChecked(true); if(v==4) ui->align->setChecked(true); if(v==5) ui->coincident->setChecked(true); setPossibleConstraints(); setPossibleOptions(); //setup all signals for event processing QObject::connect( ui->fix, SIGNAL(toggled(bool)), this, SLOT(on_constraint_selection(bool))); QObject::connect( ui->distance, SIGNAL(toggled(bool)), this, SLOT(on_constraint_selection(bool))); QObject::connect( ui->orientation, SIGNAL(toggled(bool)), this, SLOT(on_constraint_selection(bool))); QObject::connect( ui->angle, SIGNAL(toggled(bool)), this, SLOT(on_constraint_selection(bool))); QObject::connect( ui->align, SIGNAL(toggled(bool)), this, SLOT(on_constraint_selection(bool))); QObject::connect( ui->coincident, SIGNAL(toggled(bool)), this, SLOT(on_constraint_selection(bool))); QObject::connect( ui->parallel, SIGNAL(toggled(bool)), this, SLOT(on_orientation_selection(bool))); QObject::connect( ui->equal, SIGNAL(toggled(bool)), this, SLOT(on_orientation_selection(bool))); QObject::connect( ui->opposite, SIGNAL(toggled(bool)), this, SLOT(on_orientation_selection(bool))); QObject::connect( ui->perpendicular, SIGNAL(toggled(bool)), this, SLOT(on_orientation_selection(bool))); QObject::connect( ui->bidirectional, SIGNAL(toggled(bool)), this, SLOT(on_solutionspace_selection(bool))); QObject::connect( ui->pos_direction, SIGNAL(toggled(bool)), this, SLOT(on_solutionspace_selection(bool))); QObject::connect( ui->neg_direction, SIGNAL(toggled(bool)), this, SLOT(on_solutionspace_selection(bool))); QObject::connect( ui->perpendicular, SIGNAL(toggled(bool)), this, SLOT(on_orientation_selection(bool))); QObject::connect( ui->value, SIGNAL(valueChanged(double)), this, SLOT(on_value_change(double))); QObject::connect( ui->clear_first, SIGNAL(pressed()), this, SLOT(on_clear_first())); QObject::connect( ui->clear_second, SIGNAL(pressed()), this, SLOT(on_clear_second())); } dcm::Direction TaskAssemblyConstraints::getOrientation() { if(ui->parallel->isChecked()) return dcm::parallel; if(ui->equal->isChecked()) return dcm::equal; if(ui->opposite->isChecked()) return dcm::opposite; return dcm::perpendicular; } void TaskAssemblyConstraints::setOrientation(dcm::Direction d) { switch(d) { case dcm::perpendicular: ui->perpendicular->setChecked(true); break; case dcm::equal: ui->equal->setChecked(true); break; case dcm::opposite: ui->opposite->setChecked(true); break; default : ui->parallel->setChecked(true); } } dcm::SolutionSpace TaskAssemblyConstraints::getSolutionSpace() { if(ui->bidirectional->isChecked()) return dcm::bidirectional; if(ui->pos_direction->isChecked()) return dcm::positiv_directional; return dcm::negative_directional; } void TaskAssemblyConstraints::setSolutionSpace(dcm::SolutionSpace d) { switch(d) { case dcm::bidirectional: ui->bidirectional->setChecked(true); break; case dcm::positiv_directional: ui->pos_direction->setChecked(true); break; default : ui->neg_direction->setChecked(true); } } TaskAssemblyConstraints::~TaskAssemblyConstraints() { delete ui; } void TaskAssemblyConstraints::onSelectionChanged(const Gui::SelectionChanges& msg) { if(msg.Type == Gui::SelectionChanges::AddSelection) { //add it as the first geometry? if(ui->first_geom->text().isEmpty()) { std::vector objs = Gui::Selection().getSelectionEx(); Assembly::Constraint* con = dynamic_cast(view->getObject()); if(!ActiveAsmObject || !ActiveAsmObject->getTypeId().isDerivedFrom(Assembly::ItemAssembly::getClassTypeId())) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No active Assembly"), QObject::tr("You need a active (blue) Assembly to insert a Constraint. Please create a new one or make one active (double click).")); return; } std::pair part1 = static_cast(ActiveAsmObject)->getContainingPart(objs.back().getObject()); con->First.setValue(part1.first, objs.back().getSubNames()); QString str; str = QString::fromAscii(part1.first->getNameInDocument()) + QString::fromAscii(".") + QString::fromStdString(con->First.getSubValues().front()); ui->first_geom->setText(str); App::GetApplication().getActiveDocument()->recompute(); setPossibleConstraints(); setPossibleOptions(); view->draw(); return; } if(ui->second_geom->text().isEmpty()) { std::vector objs = Gui::Selection().getSelectionEx(); Assembly::Constraint* con = dynamic_cast(view->getObject()); if(!ActiveAsmObject || !ActiveAsmObject->getTypeId().isDerivedFrom(Assembly::ItemAssembly::getClassTypeId())) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No active Assembly"), QObject::tr("You need a active (blue) Assembly to insert a Constraint. Please create a new one or make one active (double click).")); return; } std::pair part2 = static_cast(ActiveAsmObject)->getContainingPart(objs.back().getObject()); con->Second.setValue(part2.first, objs.back().getSubNames()); QString str; str = QString::fromAscii(part2.first->getNameInDocument()) + QString::fromAscii(".") + QString::fromStdString(con->Second.getSubValues().front()); ui->second_geom->setText(str); App::GetApplication().getActiveDocument()->recompute(); setPossibleConstraints(); setPossibleOptions(); view->draw(); return; } }; } void TaskAssemblyConstraints::on_constraint_selection(bool clicked) { if(clicked) { Assembly::Constraint* obj = dynamic_cast(view->getObject()); if(ui->fix->isChecked()) obj->Type.setValue("Fix"); if(ui->distance->isChecked()) obj->Type.setValue("Distance"); if(ui->orientation->isChecked()) obj->Type.setValue("Orientation"); if(ui->angle->isChecked()) obj->Type.setValue("Angle"); if(ui->align->isChecked()) obj->Type.setValue("Align"); if(ui->coincident->isChecked()) obj->Type.setValue("Coincident"); App::GetApplication().getActiveDocument()->recompute(); view->draw(); } setPossibleOptions(); } void TaskAssemblyConstraints::on_orientation_selection(bool clicked) { if(clicked) { Assembly::Constraint* obj = dynamic_cast(view->getObject()); obj->Orientation.setValue(getOrientation()); App::GetApplication().getActiveDocument()->recompute(); view->draw(); } } void TaskAssemblyConstraints::on_solutionspace_selection(bool clicked) { if(clicked) { Assembly::Constraint* obj = dynamic_cast(view->getObject()); obj->SolutionSpace.setValue(getSolutionSpace()); App::GetApplication().getActiveDocument()->recompute(); view->draw(); } } void TaskAssemblyConstraints::on_value_change(double val) { Assembly::Constraint* obj = dynamic_cast(view->getObject()); obj->Value.setValue(ui->value->value()); App::GetApplication().getActiveDocument()->recompute(); view->draw(); } void TaskAssemblyConstraints::on_clear_first() { Assembly::Constraint* obj = dynamic_cast(view->getObject()); obj->First.setValue(NULL); ui->first_geom->clear(); setPossibleConstraints(); setPossibleOptions(); view->draw(); } void TaskAssemblyConstraints::on_clear_second() { Assembly::Constraint* obj = dynamic_cast(view->getObject()); obj->Second.setValue(NULL); ui->second_geom->clear(); setPossibleConstraints(); setPossibleOptions(); view->draw(); } void TaskAssemblyConstraints::setPossibleOptions() { //disable all orientations for later easy disabling ui->parallel->setEnabled(false); ui->equal->setEnabled(false); ui->opposite->setEnabled(false); ui->perpendicular->setEnabled(false); //disable solution spaces for later easy enabling ui->bidirectional->setEnabled(false); ui->pos_direction->setEnabled(false); ui->neg_direction->setEnabled(false); //this only works if both objects are set Assembly::Constraint* obj = dynamic_cast(view->getObject()); if(obj->First.getValue()) { Assembly::ItemPart* p1 = dynamic_cast(obj->First.getValue()); if(!p1) return; Assembly::ItemAssembly* ass = p1->getParentAssembly(); //extract the geometries to use for comparison boost::shared_ptr g1 = ass->m_solver->getGeometry3D(obj->First.getSubValues()[0].c_str()); if(obj->Second.getValue()) { Assembly::ItemPart* p2 = dynamic_cast(obj->Second.getValue()); if(!p2) return; boost::shared_ptr g2 = ass->m_solver->getGeometry3D(obj->Second.getSubValues()[0].c_str()); //distance if(obj->Type.getValue() == 1) { if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::plane) || isCombination(g1,g2, dcm::geometry::point, dcm::geometry::cylinder)) { ui->bidirectional->setEnabled(true); ui->pos_direction->setEnabled(true); ui->neg_direction->setEnabled(true); }; }; //align & coincident if(obj->Type.getValue() == 4 || obj->Type.getValue() == 5) { if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::plane) || isCombination(g1,g2, dcm::geometry::point, dcm::geometry::cylinder) || isCombination(g1,g2, dcm::geometry::line, dcm::geometry::plane) || isCombination(g1,g2, dcm::geometry::line, dcm::geometry::cylinder) || isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::plane) || isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::cylinder)) { ui->bidirectional->setEnabled(true); ui->pos_direction->setEnabled(true); ui->neg_direction->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::cylinder) || isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::plane) || isCombination(g1,g2, dcm::geometry::line, dcm::geometry::cylinder) || isCombination(g1,g2, dcm::geometry::cylinder, dcm::geometry::cylinder)) { ui->parallel->setEnabled(true); ui->equal->setEnabled(true); ui->opposite->setEnabled(true); //ensure that perpendicular is not checked if(ui->perpendicular->isChecked()) { ui->parallel->setChecked(true); obj->Orientation.setValue((long)0); } }; if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::plane) || isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::cylinder)) { ui->perpendicular->setEnabled(true); //ensure that perpendicular is checked if(!ui->perpendicular->isChecked()) { ui->perpendicular->setChecked(true); obj->Orientation.setValue((long)3); } }; }; //orientation if(obj->Type.getValue() == 2) { ui->parallel->setEnabled(true); ui->equal->setEnabled(true); ui->opposite->setEnabled(true); ui->perpendicular->setEnabled(true); } } } }; void TaskAssemblyConstraints::setPossibleConstraints() { //diasble all constraints for easyer enabling ui->fix->setEnabled(false); ui->distance->setEnabled(false); ui->orientation->setEnabled(false); ui->angle->setEnabled(false); ui->align->setEnabled(false); ui->coincident->setEnabled(false); Assembly::Constraint* obj = dynamic_cast(view->getObject()); if(obj->First.getValue()) { Assembly::ItemPart* p1 = dynamic_cast(obj->First.getValue()); if(!p1) return; Assembly::ItemAssembly* ass = p1->getParentAssembly(); //extract the geometries to use for comparison boost::shared_ptr g1 = ass->m_solver->getGeometry3D(obj->First.getSubValues()[0].c_str()); if(obj->Second.getValue()) { Assembly::ItemPart* p2 = dynamic_cast(obj->Second.getValue()); if(!p2) return; boost::shared_ptr g2 = ass->m_solver->getGeometry3D(obj->Second.getSubValues()[0].c_str()); //check all valid combinaions if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::point)) { ui->distance->setEnabled(true); ui->coincident->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::line)) { ui->distance->setEnabled(true); ui->coincident->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::plane)) { ui->distance->setEnabled(true); ui->coincident->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::cylinder)) { ui->distance->setEnabled(true); ui->coincident->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::line)) { ui->distance->setEnabled(true); ui->orientation->setEnabled(true); ui->angle->setEnabled(true); ui->coincident->setEnabled(true); ui->align->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::plane)) { ui->orientation->setEnabled(true); ui->angle->setEnabled(true); ui->coincident->setEnabled(true); ui->align->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::cylinder)) { ui->distance->setEnabled(true); ui->orientation->setEnabled(true); ui->angle->setEnabled(true); ui->coincident->setEnabled(true); ui->align->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::plane)) { ui->orientation->setEnabled(true); ui->angle->setEnabled(true); ui->coincident->setEnabled(true); ui->align->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::cylinder)) { ui->orientation->setEnabled(true); ui->angle->setEnabled(true); ui->align->setEnabled(true); }; if(isCombination(g1,g2, dcm::geometry::cylinder, dcm::geometry::cylinder)) { ui->coincident->setEnabled(true); ui->orientation->setEnabled(true); ui->angle->setEnabled(true); }; } else { //only fix works ui->fix->setEnabled(true); }; } } bool TaskAssemblyConstraints::isCombination(boost::shared_ptr g1, boost::shared_ptr g2, dcm::geometry::types t1, dcm::geometry::types t2) { if(g1->getGeometryType() == t1 && g2->getGeometryType() == t2) return true; if(g1->getGeometryType() == t2 && g2->getGeometryType() == t1) return true; return false; } #include "moc_TaskAssemblyConstraints.cpp"