From 680ff57ccf2c1996ce08ecaf844eddda48e49094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Sun, 4 Aug 2013 08:51:38 +0000 Subject: [PATCH] make subproduct solving work --- src/Mod/Assembly/App/ItemAssembly.cpp | 41 +- src/Mod/Assembly/App/ItemAssembly.h | 3 +- .../App/opendcm/module3d/clustermath.hpp | 9 +- .../App/opendcm/modulePart/module.hpp | 68 +++- src/Mod/Assembly/Gui/CommandConstraints.cpp | 380 +++++++++++------- .../Assembly/Gui/ViewProviderConstraint.cpp | 26 +- src/Mod/Assembly/Gui/ViewProviderConstraint.h | 2 + 7 files changed, 366 insertions(+), 163 deletions(-) diff --git a/src/Mod/Assembly/App/ItemAssembly.cpp b/src/Mod/Assembly/App/ItemAssembly.cpp index cf932865de..76c0f2a9ba 100644 --- a/src/Mod/Assembly/App/ItemAssembly.cpp +++ b/src/Mod/Assembly/App/ItemAssembly.cpp @@ -73,6 +73,11 @@ App::DocumentObjectExecReturn* ItemAssembly::execute(void) { //solve the system m_solver->solve(); + + //Parts have updated automaticly, however, currently there are no signals + //for subsystems. We have to retrieve the product placements therefore by hand + finish(boost::shared_ptr()); + } catch(dcm::solving_error& e) { Base::Console().Error("Solver failed with error %i: %s", *boost::get_error_info(e), @@ -163,7 +168,7 @@ ItemAssembly* ItemAssembly::getParentAssembly(ItemPart* part) { -ItemPart* ItemAssembly::getContainingPart(App::DocumentObject* obj) { +std::pair ItemAssembly::getContainingPart(App::DocumentObject* obj) { typedef std::vector::const_iterator iter; @@ -172,22 +177,24 @@ ItemPart* ItemAssembly::getContainingPart(App::DocumentObject* obj) { if((*it)->getTypeId() == Assembly::ItemPart::getClassTypeId()) { if(static_cast(*it)->holdsObject(obj)) - return static_cast(*it); + return std::make_pair(static_cast(*it), this); } else if((*it)->getTypeId() == Assembly::ItemAssembly::getClassTypeId()) { - Assembly::ItemPart* part = static_cast(*it)->getContainingPart(obj); - if(part) + std::pair part = static_cast(*it)->getContainingPart(obj); + if(part.first && part.second) return part; } }; - return NULL; + return std::pair(NULL, NULL); } void ItemAssembly::init(boost::shared_ptr parent) { - if(parent) + if(parent) { m_solver = boost::shared_ptr(parent->createSubsystem()); + m_solver->setTransformation(this->Placement.getValue()); + } typedef std::vector::const_iterator iter; @@ -201,5 +208,27 @@ void ItemAssembly::init(boost::shared_ptr parent) { }; } +//no signals for subsystems, we need to extract the placement by hand +void ItemAssembly::finish(boost::shared_ptr parent) { + + Base::Console().Message("finish\n"); + if(parent) { + Base::Console().Message("set product placement\n"); + Base::Placement p = m_solver->getTransformation(); + this->Placement.setValue(p); + } + + typedef std::vector::const_iterator iter; + + const std::vector& vector = Items.getValues(); + for(iter it=vector.begin(); it != vector.end(); it++) { + + if((*it)->getTypeId() == Assembly::ItemAssembly::getClassTypeId()) { + + static_cast(*it)->finish(m_solver); + } + }; +} + } diff --git a/src/Mod/Assembly/App/ItemAssembly.h b/src/Mod/Assembly/App/ItemAssembly.h index f9050c55d0..9a7c2a2cc7 100644 --- a/src/Mod/Assembly/App/ItemAssembly.h +++ b/src/Mod/Assembly/App/ItemAssembly.h @@ -60,8 +60,9 @@ public: bool isParentAssembly(ItemPart* part); ItemAssembly* getParentAssembly(ItemPart* part); - ItemPart* getContainingPart(App::DocumentObject* obj); + std::pair< ItemPart*, ItemAssembly* > getContainingPart(App::DocumentObject* obj); void init(boost::shared_ptr parent); + void finish(boost::shared_ptr parent); boost::shared_ptr m_solver; }; diff --git a/src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp b/src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp index 2d44b1995a..989ad3e0cc 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp @@ -418,7 +418,7 @@ std::vector::Geom>& ClusterMath::getGeometry() { template ClusterMath::map_downstream::map_downstream(details::ClusterMath& cm, bool fix) : m_clusterMath(cm), m_isFixed(fix) { - m_transform = m_clusterMath.getTransform(); + m_transform = m_clusterMath.getTransform().inverse(); }; template @@ -431,13 +431,12 @@ void ClusterMath::map_downstream::operator()(Geom g) { //position and offset of the parameters must be set to the clusters values g->setClusterMode(true, m_isFixed); //calculate the appropriate local values - typename Kernel::Transform3D trans = m_transform.inverse(); - g->transform(trans); + g->transform(m_transform); }; template void ClusterMath::map_downstream::operator()(boost::shared_ptr c) { - m_transform *= c->template getClusterProperty().getTransform(); + m_transform *= c->template getClusterProperty().getTransform().inverse(); }; @@ -481,7 +480,7 @@ typename ClusterMath::Scalar ClusterMath::calculateClusterScale() { m_points.push_back((*it)->getPoint()); //start scale calculation - if(m_points.empty()) assert(false); //TODO: Throw + if(m_points.empty()) return 1.; else if(m_points.size() == 1) { const typename Kernel::Vector3 p = m_points[0]; return calcOnePoint(p); diff --git a/src/Mod/Assembly/App/opendcm/modulePart/module.hpp b/src/Mod/Assembly/App/opendcm/modulePart/module.hpp index 208cd49cd8..8334c2c8a6 100644 --- a/src/Mod/Assembly/App/opendcm/modulePart/module.hpp +++ b/src/Mod/Assembly/App/opendcm/modulePart/module.hpp @@ -98,6 +98,9 @@ struct ModulePart { } Transform& m_transform; }; + + //collect all clustergraph upstream cluster transforms + void transform_traverse(Transform& t, boost::shared_ptr c); public: using Object::m_system; @@ -113,6 +116,15 @@ struct ModulePart { template void set(const T& geometry); + + //access the parts transformation + template + T& get(); + + //get the transformation from part local to overall global. In multi layer systems + //this means the successive transformation from this part to the toplevel cluster + template + T getGlobal(); virtual boost::shared_ptr clone(Sys& newSys); @@ -276,6 +288,9 @@ ModulePart::type::Part_base::Part_base(const T& geometry, Sys cluster->template setClusterProperty(false); + //the the clustermath transform + m_cluster->template getClusterProperty().getTransform() = m_transform; + #ifdef USE_LOGGING BOOST_LOG(log) << "Init: "< typename ModulePart::template type::Part_base::Geom ModulePart::type::Part_base::addGeometry3D(const T& geom, CoordinateFrame frame) { Geom g(new Geometry3D(geom, *m_system)); - if(frame == Local) - g->transform(m_transform); + + if(frame == Local) { + //we need to collect all transforms up to this part! + Transform t; + transform_traverse(t, m_cluster); + + g->transform(t); + } fusion::vector res = m_cluster->addVertex(); m_cluster->template setObject (fusion::at_c<0> (res), g); @@ -305,6 +326,19 @@ ModulePart::type::Part_base::addGeometry3D(const T& geom, Coo return g; }; +template +template +void ModulePart::type::Part_base::transform_traverse(ModulePart::type::Part_base::Transform& t, + boost::shared_ptr::type::Part_base::Cluster> c) { + + t *= c->template getClusterProperty().m_transform; + + if(c->isRoot()) + return; + + transform_traverse(t, c->parent()); +} + template template template @@ -312,6 +346,34 @@ void ModulePart::type::Part_base::set(const T& geometry) { Part_base::m_geometry = geometry; (typename geometry_traits::modell()).template extract::accessor >(geometry, Part_base::m_transform); + + //set the clustermath transform + m_cluster->template getClusterProperty().getTransform() = m_transform; +}; + +template +template +template +T& ModulePart::type::Part_base::get() { + + return get(this); +}; + +template +template +template +T ModulePart::type::Part_base::getGlobal() { + + //get the successive transform + Transform t; + transform_traverse(t, m_cluster); + + //put it into the user type + T ut; + (typename geometry_traits::modell()).template inject::accessor >(ut, t); + + return ut; }; template @@ -564,3 +626,5 @@ void ModulePart::type::EvaljuateCluster::execute(Sys& sys) { + + diff --git a/src/Mod/Assembly/Gui/CommandConstraints.cpp b/src/Mod/Assembly/Gui/CommandConstraints.cpp index d415c9d38a..98653c51c4 100644 --- a/src/Mod/Assembly/Gui/CommandConstraints.cpp +++ b/src/Mod/Assembly/Gui/CommandConstraints.cpp @@ -40,29 +40,31 @@ using namespace std; -extern Assembly::Item *ActiveAsmObject; +extern Assembly::Item* ActiveAsmObject; // Helper methods =========================================================== -Assembly::ConstraintGroup * getConstraintGroup(Assembly::ItemAssembly *Asm) +Assembly::ConstraintGroup* getConstraintGroup(Assembly::ItemAssembly* Asm) { - Assembly::ConstraintGroup *ConstGrp = 0; + Assembly::ConstraintGroup* ConstGrp = 0; std::vector Ano = Asm->Annotations.getValues(); - for(std::vector::const_iterator it = Ano.begin();it!=Ano.end();++it){ - if((*it)->getTypeId().isDerivedFrom(Assembly::ConstraintGroup::getClassTypeId() )){ + + for(std::vector::const_iterator it = Ano.begin(); it != Ano.end(); ++it) { + if((*it)->getTypeId().isDerivedFrom(Assembly::ConstraintGroup::getClassTypeId())) { ConstGrp = static_cast(*it); break; } } + return ConstGrp; } -bool getConstraintPrerequisits(Assembly::ItemAssembly **Asm,Assembly::ConstraintGroup **ConstGrp) +bool getConstraintPrerequisits(Assembly::ItemAssembly** Asm, Assembly::ConstraintGroup** ConstGrp) { - if(!ActiveAsmObject || !ActiveAsmObject->getTypeId().isDerivedFrom(Assembly::ItemAssembly::getClassTypeId())){ + 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).")); + QObject::tr("You need a active (blue) Assembly to insert a Constraint. Please create a new one or make one active (double click).")); return true; } @@ -70,15 +72,18 @@ bool getConstraintPrerequisits(Assembly::ItemAssembly **Asm,Assembly::Constraint // find the Constraint group of the active Assembly *ConstGrp = getConstraintGroup(*Asm); + // if it hasen't aleardy one, create one: - if(!*ConstGrp){ - Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().addObject('Assembly::ConstraintGroup','ConstraintGroup')"); - Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().ActiveObject.Label = 'ConstraintGroup'"); - Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Annotations = App.activeDocument().%s.Annotations + [App.activeDocument().ActiveObject]",(*Asm)->getNameInDocument(),(*Asm)->getNameInDocument()); + if(!*ConstGrp) { + Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().addObject('Assembly::ConstraintGroup','ConstraintGroup')"); + Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().ActiveObject.Label = 'ConstraintGroup'"); + Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().%s.Annotations = App.activeDocument().%s.Annotations + [App.activeDocument().ActiveObject]", (*Asm)->getNameInDocument(), (*Asm)->getNameInDocument()); } + // find now *ConstGrp = getConstraintGroup(*Asm); + if(!*ConstGrp) throw Base::Exception("Could not create Assembly::ConstraintGroup in active Assembly"); @@ -87,13 +92,14 @@ bool getConstraintPrerequisits(Assembly::ItemAssembly **Asm,Assembly::Constraint } -std::string asSubLinkString(Assembly::ItemPart* part, std::string element) { - std::string buf; +std::string asSubLinkString(Assembly::ItemPart* part, std::string element) +{ + std::string buf; buf += "(App.ActiveDocument."; - buf += part->getNameInDocument(); + buf += part->getNameInDocument(); buf += ",['"; buf += element; - buf += "'])"; + buf += "'])"; return buf; } @@ -102,7 +108,7 @@ std::string asSubLinkString(Assembly::ItemPart* part, std::string element) { DEF_STD_CMD(CmdAssemblyConstraintDistance); CmdAssemblyConstraintDistance::CmdAssemblyConstraintDistance() - :Command("Assembly_ConstraintDistance") + : Command("Assembly_ConstraintDistance") { sAppModule = "Assembly"; sGroup = QT_TR_NOOP("Assembly"); @@ -116,45 +122,57 @@ CmdAssemblyConstraintDistance::CmdAssemblyConstraintDistance() void CmdAssemblyConstraintDistance::activated(int iMsg) { - Assembly::ItemAssembly *Asm=0; - Assembly::ConstraintGroup *ConstGrp=0; + Assembly::ItemAssembly* Asm = 0; + Assembly::ConstraintGroup* ConstGrp = 0; // retrive the standard objects needed - if(getConstraintPrerequisits(&Asm,&ConstGrp)) + if(getConstraintPrerequisits(&Asm, &ConstGrp)) return; - + std::vector objs = Gui::Selection().getSelectionEx(); + if(objs.size() != 2) { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("You need to select two geometries on two different parts")); + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("You need to select two geometries on two different parts")); return; }; - - Assembly::ItemPart* part1 = Asm->getContainingPart(objs[0].getObject()); - Assembly::ItemPart* part2 = Asm->getContainingPart(objs[1].getObject()); - if(!part1 || !part2) { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); + + std::pair part1 = Asm->getContainingPart(objs[0].getObject()); + std::pair part2 = Asm->getContainingPart(objs[1].getObject()); + + //checking the parts is enough, both or non! + if(!part1.first || !part2.first) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); return; }; - + + //check if this is the right place for the constraint + if( (part1.second == part2.second) && part1.second != Asm ) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("The selected parts belong both to the same subproduct, please add constraints there")); + return; + } + bool ok; + double d = QInputDialog::getDouble(NULL, QObject::tr("Constraint value"), - QObject::tr("Distance:"), 0., -10000., 10000., 2, &ok); + QObject::tr("Distance:"), 0., -10000., 10000., 2, &ok); + if(!ok) - return; - + return; + openCommand("Insert Constraint Distance"); std::string ConstrName = getUniqueObjectName("Distance"); - doCommand(Doc,"App.activeDocument().addObject('Assembly::ConstraintDistance','%s')",ConstrName.c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1, objs[0].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2, objs[1].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Distance = %f", d); - doCommand(Doc,"App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]",ConstGrp->getNameInDocument(),ConstGrp->getNameInDocument()); - + doCommand(Doc, "App.activeDocument().addObject('Assembly::ConstraintDistance','%s')", ConstrName.c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1.first, objs[0].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2.first, objs[1].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Distance = %f", d); + doCommand(Doc, "App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]", ConstGrp->getNameInDocument(), ConstGrp->getNameInDocument()); + commitCommand(); updateActive(); - + } /******************************************************************************************/ @@ -162,7 +180,7 @@ void CmdAssemblyConstraintDistance::activated(int iMsg) DEF_STD_CMD(CmdAssemblyConstraintFix); CmdAssemblyConstraintFix::CmdAssemblyConstraintFix() - :Command("Assembly_ConstraintFix") + : Command("Assembly_ConstraintFix") { sAppModule = "Assembly"; sGroup = QT_TR_NOOP("Assembly"); @@ -176,43 +194,56 @@ CmdAssemblyConstraintFix::CmdAssemblyConstraintFix() void CmdAssemblyConstraintFix::activated(int iMsg) { - Assembly::ItemAssembly *Asm=0; - Assembly::ConstraintGroup *ConstGrp=0; + Assembly::ItemAssembly* Asm = 0; + Assembly::ConstraintGroup* ConstGrp = 0; // retrive the standard objects needed - if(getConstraintPrerequisits(&Asm,&ConstGrp)) + if(getConstraintPrerequisits(&Asm, &ConstGrp)) return; - + std::vector objs = Gui::Selection().getSelectionEx(); + if(objs.size() != 1) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("You need to select one part only")); + QObject::tr("You need to select one part only")); + return; + }; + + std::pair part = Asm->getContainingPart(objs[0].getObject()); + + if(!part.first) { + Base::Console().Message("The selected part need to belong to the active assembly\n"); return; }; - Assembly::ItemPart* part = Asm->getContainingPart(objs[0].getObject()); - if(!part) { - Base::Console().Message("The selected object need to belong to the active assembly\n"); + if(part.second != Asm) { + Base::Console().Message("The selected part need belongs to an subproduct, please add constraint there\n"); return; - }; - + } + openCommand("Insert Constraint Fix"); + std::string ConstrName = getUniqueObjectName("Fix"); - doCommand(Doc,"App.activeDocument().addObject('Assembly::ConstraintFix','%s')",ConstrName.c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.First = %s", asSubLinkString(part, objs[0].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]",ConstGrp->getNameInDocument(),ConstGrp->getNameInDocument()); - + + doCommand(Doc, "App.activeDocument().addObject('Assembly::ConstraintFix','%s')", ConstrName.c_str()); + + doCommand(Doc, "App.activeDocument().ActiveObject.First = %s", asSubLinkString(part.first, objs[0].getSubNames()[0]).c_str()); + + doCommand(Doc, "App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]", ConstGrp->getNameInDocument(), ConstGrp->getNameInDocument()); + commitCommand(); + updateActive(); } + /******************************************************************************************/ DEF_STD_CMD(CmdAssemblyConstraintAngle); CmdAssemblyConstraintAngle::CmdAssemblyConstraintAngle() - :Command("Assembly_ConstraintAngle") + : Command("Assembly_ConstraintAngle") { sAppModule = "Assembly"; sGroup = QT_TR_NOOP("Assembly"); @@ -226,45 +257,57 @@ CmdAssemblyConstraintAngle::CmdAssemblyConstraintAngle() void CmdAssemblyConstraintAngle::activated(int iMsg) { - Assembly::ItemAssembly *Asm=0; - Assembly::ConstraintGroup *ConstGrp=0; + Assembly::ItemAssembly* Asm = 0; + Assembly::ConstraintGroup* ConstGrp = 0; // retrive the standard objects needed - if(getConstraintPrerequisits(&Asm,&ConstGrp)) + if(getConstraintPrerequisits(&Asm, &ConstGrp)) return; - + std::vector objs = Gui::Selection().getSelectionEx(); + if(objs.size() != 2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("You need to select two geometries on two different parts")); + QObject::tr("You need to select two geometries on two different parts")); return; }; - - Assembly::ItemPart* part1 = Asm->getContainingPart(objs[0].getObject()); - Assembly::ItemPart* part2 = Asm->getContainingPart(objs[1].getObject()); - if(!part1 || !part2) { + + std::pair part1 = Asm->getContainingPart(objs[0].getObject()); + std::pair part2 = Asm->getContainingPart(objs[1].getObject()); + + //checking the parts is enough, both or non! + if(!part1.first || !part2.first) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); + QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); return; }; - + + //check if this is the right place for the constraint + if( ( (part1.second == part2.second) && part1.second != Asm ) && part1.second != Asm ) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("The selected parts belong both to the same subproduct, please add constraints there")); + return; + } + bool ok; + double d = QInputDialog::getDouble(NULL, QObject::tr("Constraint value"), - QObject::tr("Angle:"), 0., 0., 360., 2, &ok); + QObject::tr("Angle:"), 0., 0., 360., 2, &ok); + if(!ok) - return; - + return; + openCommand("Insert Constraint Angle"); std::string ConstrName = getUniqueObjectName("Angle"); - doCommand(Doc,"App.activeDocument().addObject('Assembly::ConstraintAngle','%s')",ConstrName.c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1, objs[0].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2, objs[1].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Angle = %f", d); - doCommand(Doc,"App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]",ConstGrp->getNameInDocument(),ConstGrp->getNameInDocument()); - + doCommand(Doc, "App.activeDocument().addObject('Assembly::ConstraintAngle','%s')", ConstrName.c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1.first, objs[0].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2.first, objs[1].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Angle = %f", d); + doCommand(Doc, "App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]", ConstGrp->getNameInDocument(), ConstGrp->getNameInDocument()); + commitCommand(); updateActive(); - + } @@ -274,7 +317,7 @@ void CmdAssemblyConstraintAngle::activated(int iMsg) DEF_STD_CMD(CmdAssemblyConstraintOrientation); CmdAssemblyConstraintOrientation::CmdAssemblyConstraintOrientation() - :Command("Assembly_ConstraintOrientation") + : Command("Assembly_ConstraintOrientation") { sAppModule = "Assembly"; sGroup = QT_TR_NOOP("Assembly"); @@ -288,48 +331,61 @@ CmdAssemblyConstraintOrientation::CmdAssemblyConstraintOrientation() void CmdAssemblyConstraintOrientation::activated(int iMsg) { - Assembly::ItemAssembly *Asm=0; - Assembly::ConstraintGroup *ConstGrp=0; + Assembly::ItemAssembly* Asm = 0; + Assembly::ConstraintGroup* ConstGrp = 0; // retrive the standard objects needed - if(getConstraintPrerequisits(&Asm,&ConstGrp)) + if(getConstraintPrerequisits(&Asm, &ConstGrp)) return; - + std::vector objs = Gui::Selection().getSelectionEx(); + if(objs.size() != 2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("You need to select two geometries on two different parts")); + QObject::tr("You need to select two geometries on two different parts")); return; }; - - Assembly::ItemPart* part1 = Asm->getContainingPart(objs[0].getObject()); - Assembly::ItemPart* part2 = Asm->getContainingPart(objs[1].getObject()); - if(!part1 || !part2) { + + std::pair part1 = Asm->getContainingPart(objs[0].getObject()); + std::pair part2 = Asm->getContainingPart(objs[1].getObject()); + + //checking the parts is enough, both or non! + if(!part1.first || !part2.first) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); + QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); return; }; - + + //check if this is the right place for the constraint + if( (part1.second == part2.second) && part1.second != Asm ) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("The selected parts belong both to the same subproduct, please add constraints there")); + return; + } + QStringList items; + items << QObject::tr("Parallel") << QObject::tr("Perpendicular") << QObject::tr("Equal") << QObject::tr("Opposite"); bool ok; + QString item = QInputDialog::getItem(NULL, QObject::tr("Constraint value"), - QObject::tr("Orientation:"), items, 0, false, &ok); - if (!ok || item.isEmpty()) + QObject::tr("Orientation:"), items, 0, false, &ok); + + if(!ok || item.isEmpty()) return; - + openCommand("Insert Constraint Orientation"); std::string ConstrName = getUniqueObjectName("Orientation"); - doCommand(Doc,"App.activeDocument().addObject('Assembly::ConstraintOrientation','%s')",ConstrName.c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1, objs[0].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2, objs[1].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Orientation = '%s'", item.toStdString().c_str()); - doCommand(Doc,"App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]",ConstGrp->getNameInDocument(),ConstGrp->getNameInDocument()); - + doCommand(Doc, "App.activeDocument().addObject('Assembly::ConstraintOrientation','%s')", ConstrName.c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1.first, objs[0].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2.first, objs[1].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Orientation = '%s'", item.toStdString().c_str()); + doCommand(Doc, "App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]", ConstGrp->getNameInDocument(), ConstGrp->getNameInDocument()); + commitCommand(); updateActive(); - + } /******************************************************************************************/ @@ -338,7 +394,7 @@ void CmdAssemblyConstraintOrientation::activated(int iMsg) DEF_STD_CMD(CmdAssemblyConstraintCoincidence); CmdAssemblyConstraintCoincidence::CmdAssemblyConstraintCoincidence() - :Command("Assembly_ConstraintCoincidence") + : Command("Assembly_ConstraintCoincidence") { sAppModule = "Assembly"; sGroup = QT_TR_NOOP("Assembly"); @@ -352,48 +408,61 @@ CmdAssemblyConstraintCoincidence::CmdAssemblyConstraintCoincidence() void CmdAssemblyConstraintCoincidence::activated(int iMsg) { - Assembly::ItemAssembly *Asm=0; - Assembly::ConstraintGroup *ConstGrp=0; + Assembly::ItemAssembly* Asm = 0; + Assembly::ConstraintGroup* ConstGrp = 0; // retrive the standard objects needed - if(getConstraintPrerequisits(&Asm,&ConstGrp)) + if(getConstraintPrerequisits(&Asm, &ConstGrp)) return; - + std::vector objs = Gui::Selection().getSelectionEx(); + if(objs.size() != 2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("You need to select two geometries on two different parts")); + QObject::tr("You need to select two geometries on two different parts")); return; }; - - Assembly::ItemPart* part1 = Asm->getContainingPart(objs[0].getObject()); - Assembly::ItemPart* part2 = Asm->getContainingPart(objs[1].getObject()); - if(!part1 || !part2) { + + std::pair part1 = Asm->getContainingPart(objs[0].getObject()); + std::pair part2 = Asm->getContainingPart(objs[1].getObject()); + + //checking the parts is enough, both or non! + if(!part1.first || !part2.first) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); + QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); return; }; - + + //check if this is the right place for the constraint + if( (part1.second == part2.second) && part1.second != Asm ) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("The selected parts belong both to the same subproduct, please add constraints there")); + return; + } + QStringList items; + items << QObject::tr("Parallel") << QObject::tr("Equal") << QObject::tr("Opposite"); bool ok; + QString item = QInputDialog::getItem(NULL, QObject::tr("Constraint value"), - QObject::tr("Orientation:"), items, 0, false, &ok); - if (!ok || item.isEmpty()) + QObject::tr("Orientation:"), items, 0, false, &ok); + + if(!ok || item.isEmpty()) return; - + openCommand("Insert Constraint Coincidence"); std::string ConstrName = getUniqueObjectName("Coincidence"); - doCommand(Doc,"App.activeDocument().addObject('Assembly::ConstraintCoincidence','%s')",ConstrName.c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1, objs[0].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2, objs[1].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Orientation = '%s'", item.toStdString().c_str()); - doCommand(Doc,"App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]",ConstGrp->getNameInDocument(),ConstGrp->getNameInDocument()); - + doCommand(Doc, "App.activeDocument().addObject('Assembly::ConstraintCoincidence','%s')", ConstrName.c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1.first, objs[0].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2.first, objs[1].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Orientation = '%s'", item.toStdString().c_str()); + doCommand(Doc, "App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]", ConstGrp->getNameInDocument(), ConstGrp->getNameInDocument()); + commitCommand(); updateActive(); - + } /******************************************************************************************/ @@ -402,7 +471,7 @@ void CmdAssemblyConstraintCoincidence::activated(int iMsg) DEF_STD_CMD(CmdAssemblyConstraintAlignment); CmdAssemblyConstraintAlignment::CmdAssemblyConstraintAlignment() - :Command("Assembly_ConstraintAlignment") + : Command("Assembly_ConstraintAlignment") { sAppModule = "Assembly"; sGroup = QT_TR_NOOP("Assembly"); @@ -416,55 +485,70 @@ CmdAssemblyConstraintAlignment::CmdAssemblyConstraintAlignment() void CmdAssemblyConstraintAlignment::activated(int iMsg) { - Assembly::ItemAssembly *Asm=0; - Assembly::ConstraintGroup *ConstGrp=0; + Assembly::ItemAssembly* Asm = 0; + Assembly::ConstraintGroup* ConstGrp = 0; // retrive the standard objects needed - if(getConstraintPrerequisits(&Asm,&ConstGrp)) + if(getConstraintPrerequisits(&Asm, &ConstGrp)) return; - + std::vector objs = Gui::Selection().getSelectionEx(); + if(objs.size() != 2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("You need to select two geometries on two different parts")); + QObject::tr("You need to select two geometries on two different parts")); return; }; - - Assembly::ItemPart* part1 = Asm->getContainingPart(objs[0].getObject()); - Assembly::ItemPart* part2 = Asm->getContainingPart(objs[1].getObject()); - if(!part1 || !part2) { + + std::pair part1 = Asm->getContainingPart(objs[0].getObject()); + std::pair part2 = Asm->getContainingPart(objs[1].getObject()); + + //checking the parts is enough, both or non! + if(!part1.first || !part2.first) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); + QObject::tr("The selected parts need to belong to the active assembly (active product or one of it's subproducts)")); return; }; - + + //check if this is the right place for the constraint + if( (part1.second == part2.second) && part1.second != Asm ) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("The selected parts belong both to the same subproduct, please add constraints there")); + return; + } + QStringList items; + items << QObject::tr("Parallel") << QObject::tr("Equal") << QObject::tr("Opposite"); QDialog dialog; - Ui_AlignmentDialog ui; + + Ui_AlignmentDialog ui; + ui.setupUi(&dialog); + ui.comboBox->addItems(items); - if( dialog.exec() != QDialog::Accepted ) - return; - + + if(dialog.exec() != QDialog::Accepted) + return; + openCommand("Insert Constraint Alignment"); std::string ConstrName = getUniqueObjectName("Alignment"); - doCommand(Doc,"App.activeDocument().addObject('Assembly::ConstraintAlignment','%s')",ConstrName.c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1, objs[0].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2, objs[1].getSubNames()[0]).c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Orientation = '%s'", ui.comboBox->currentText().toStdString().c_str()); - doCommand(Doc,"App.activeDocument().ActiveObject.Offset = %f", ui.doubleSpinBox->value()); - doCommand(Doc,"App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]",ConstGrp->getNameInDocument(),ConstGrp->getNameInDocument()); - + doCommand(Doc, "App.activeDocument().addObject('Assembly::ConstraintAlignment','%s')", ConstrName.c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.First = %s", asSubLinkString(part1.first, objs[0].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Second = %s", asSubLinkString(part2.first, objs[1].getSubNames()[0]).c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Orientation = '%s'", ui.comboBox->currentText().toStdString().c_str()); + doCommand(Doc, "App.activeDocument().ActiveObject.Offset = %f", ui.doubleSpinBox->value()); + doCommand(Doc, "App.activeDocument().%s.Constraints = App.activeDocument().%s.Constraints + [App.activeDocument().ActiveObject]", ConstGrp->getNameInDocument(), ConstGrp->getNameInDocument()); + commitCommand(); updateActive(); - + } void CreateAssemblyConstraintCommands(void) { - Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); rcCmdMgr.addCommand(new CmdAssemblyConstraintFix()); rcCmdMgr.addCommand(new CmdAssemblyConstraintDistance()); @@ -472,4 +556,6 @@ void CreateAssemblyConstraintCommands(void) rcCmdMgr.addCommand(new CmdAssemblyConstraintOrientation()); rcCmdMgr.addCommand(new CmdAssemblyConstraintCoincidence()); rcCmdMgr.addCommand(new CmdAssemblyConstraintAlignment()); - } +} + + diff --git a/src/Mod/Assembly/Gui/ViewProviderConstraint.cpp b/src/Mod/Assembly/Gui/ViewProviderConstraint.cpp index d7c5ed7002..f52b9d40fc 100644 --- a/src/Mod/Assembly/Gui/ViewProviderConstraint.cpp +++ b/src/Mod/Assembly/Gui/ViewProviderConstraint.cpp @@ -232,7 +232,8 @@ void ViewProviderConstraint::draw() TopLoc_Location l1 = s1.Location(); gp_XYZ tr1 = l1.Transformation().TranslationPart(); Base::Placement p1(Base::Vector3d(tr1.X(), tr1.Y(), tr1.Z()), Base::Rotation()); - p1 = part1->Placement.getValue() * p1; + upstream_placement(p1, part1); + //p1 = part1->m_part->getGlobal() * p1; float q0 = (float)p1.getRotation().getValue()[0]; float q1 = (float)p1.getRotation().getValue()[1]; @@ -265,11 +266,32 @@ void ViewProviderConstraint::draw() TopLoc_Location l2 = s2.Location(); gp_XYZ tr2 = l2.Transformation().TranslationPart(); Base::Placement p2(Base::Vector3d(tr2.X(), tr2.Y(), tr2.Z()), Base::Rotation()); + upstream_placement(p2, part2); - p2 = p1.inverse() * (part2->Placement.getValue() * p2); + p2 = p1.inverse()*p2; + //p2 = p1.inverse() * (part2->m_part->getGlobal() * p2); internal_vp.updatePlacement(p2); } +void ViewProviderConstraint::upstream_placement(Base::Placement& p, Assembly::Item* item) { + + //successive transformation for this item + p = item->Placement.getValue() * p; + + typedef std::vector::const_iterator iter; + + //get all links to this item and see if we have more ItemAssemblys + const std::vector& vector = item->getInList(); + for(iter it=vector.begin(); it != vector.end(); it++) { + + if((*it)->getTypeId() == Assembly::ItemAssembly::getClassTypeId()) { + + upstream_placement(p, static_cast(*it)); + return; + } + }; +}; + void ViewProviderConstraint::onSelectionChanged(const Gui::SelectionChanges& msg) { if(Gui::Selection().isSelected(pcObject) && Visibility.getValue()) { diff --git a/src/Mod/Assembly/Gui/ViewProviderConstraint.h b/src/Mod/Assembly/Gui/ViewProviderConstraint.h index 83547f8fc2..cedcfcfef0 100644 --- a/src/Mod/Assembly/Gui/ViewProviderConstraint.h +++ b/src/Mod/Assembly/Gui/ViewProviderConstraint.h @@ -28,6 +28,7 @@ #include #include #include +#include "Mod/Assembly/App/Item.h" namespace AssemblyGui { @@ -88,6 +89,7 @@ private: //update visualisation and placements of the scenegraph void draw(); + void upstream_placement(Base::Placement& p, Assembly::Item* item); //watch if something got selected in the tree virtual void onSelectionChanged(const Gui::SelectionChanges& msg);