diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 948748fcc..b8ca0f770 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -941,10 +941,12 @@ void Application::init(int argc, char ** argv) #endif // if an unexpected crash occurs we can install a handler function to // write some additional information +#ifdef _MSC_VER // Microsoft compiler std::signal(SIGSEGV,segmentation_fault_handler); std::signal(SIGABRT,segmentation_fault_handler); std::set_terminate(unhandled_exception_handler); std::set_unexpected(unexpection_error_handler); +#endif initTypes(); diff --git a/src/Mod/PartDesign/App/FeaturePocket.cpp b/src/Mod/PartDesign/App/FeaturePocket.cpp index 5779e32a1..351fb512d 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.cpp +++ b/src/Mod/PartDesign/App/FeaturePocket.cpp @@ -168,6 +168,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void) TopoDS_Shape solRes = this->getSolid(result); if (solRes.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Resulting shape is not a solid"); + remapSupportShape(solRes); this->Shape.setValue(solRes); } diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index c09b1425b..490447184 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -41,11 +41,13 @@ # include # include # include +# include # include # include # include # include # include +# include # include # include # include @@ -519,4 +521,147 @@ const bool SketchBased::checkWireInsideFace(const TopoDS_Wire& wire, const TopoD return (proj.More() && proj.Current().Closed()); } +void SketchBased::remapSupportShape(const TopoDS_Shape& newShape) +{ + std::vector refs = this->getInList(); + for (std::vector::iterator it = refs.begin(); it != refs.end(); ++it) { + if ((*it)->isDerivedFrom(Part::Part2DObject::getClassTypeId())) { + Part::Part2DObject* part = static_cast(*it); + Part::TopoShape shape = this->Shape.getValue(); + // here we must reset the placement otherwise the geometric matching doesn't work + shape._Shape.Location(TopLoc_Location()); + std::vector subValues = part->Support.getSubValues(); + std::vector newSubValues; + TopTools_IndexedMapOfShape faceMap; + TopExp::MapShapes(newShape, TopAbs_FACE, faceMap); + + for (std::vector::iterator it = subValues.begin(); it != subValues.end(); ++it) { + std::string shapetype; + if (it->size() > 4 && it->substr(0,4) == "Face") { + shapetype = "Face"; + } + else if (it->size() > 4 && it->substr(0,4) == "Edge") { + shapetype = "Edge"; + } + else if (it->size() > 6 && it->substr(0,6) == "Vertex") { + shapetype = "Vertex"; + } + else { + continue; + } + + TopoDS_Shape element = shape.getSubShape(it->c_str()); + bool success = false; + // first try an exact matching + for (int i=1; iSupport.setValue(this, newSubValues); + } + } +} + +struct gp_Pnt_Less : public std::binary_function +{ + bool operator()(const gp_Pnt& p1, + const gp_Pnt& p2) const + { + if (fabs(p1.X() - p2.X()) > Precision::Confusion()) + return p1.X() < p2.X(); + if (fabs(p1.Y() - p2.Y()) > Precision::Confusion()) + return p1.Y() < p2.Y(); + if (fabs(p1.Z() - p2.Z()) > Precision::Confusion()) + return p1.Z() < p2.Z(); + return false; // points are considered to be equal + } +}; + +bool SketchBased::isQuasiEqual(const TopoDS_Shape& s1, const TopoDS_Shape& s2) const +{ + if (s1.ShapeType() != s2.ShapeType()) + return false; + TopTools_IndexedMapOfShape map1, map2; + TopExp::MapShapes(s1, TopAbs_VERTEX, map1); + TopExp::MapShapes(s2, TopAbs_VERTEX, map2); + if (map1.Extent() != map2.Extent()) + return false; + + std::vector p1; + for (int i=1; i<=map1.Extent(); i++) { + const TopoDS_Vertex& v = TopoDS::Vertex(map1.FindKey(i)); + p1.push_back(BRep_Tool::Pnt(v)); + } + std::vector p2; + for (int i=1; i<=map2.Extent(); i++) { + const TopoDS_Vertex& v = TopoDS::Vertex(map2.FindKey(i)); + p2.push_back(BRep_Tool::Pnt(v)); + } + + std::sort(p1.begin(), p1.end(), gp_Pnt_Less()); + std::sort(p2.begin(), p2.end(), gp_Pnt_Less()); + + if (p1.size() != p2.size()) + return false; + + std::vector::iterator it = p1.begin(), jt = p2.begin(); + for (; it != p1.end(); ++it, ++jt) { + if (!(*it).IsEqual(*jt, Precision::Confusion())) + return false; + } + + return true; +} + +bool SketchBased::isEqualGeometry(const TopoDS_Shape& s1, const TopoDS_Shape& s2) +{ + if (s1.ShapeType() == TopAbs_FACE && s2.ShapeType() == TopAbs_FACE) { + BRepAdaptor_Surface a1(TopoDS::Face(s1)); + BRepAdaptor_Surface a2(TopoDS::Face(s2)); + if (a1.GetType() == GeomAbs_Plane && a2.GetType() == GeomAbs_Plane) { + gp_Pln p1 = a1.Plane(); + gp_Pln p2 = a2.Plane(); + if (p1.Distance(p2.Location()) < Precision::Confusion()) { + const gp_Dir& d1 = p1.Axis().Direction(); + const gp_Dir& d2 = p2.Axis().Direction(); + if (d1.IsParallel(d2, Precision::Confusion())) + return true; + } + } + } + else if (s1.ShapeType() == TopAbs_EDGE && s2.ShapeType() == TopAbs_EDGE) { + } + else if (s1.ShapeType() == TopAbs_VERTEX && s2.ShapeType() == TopAbs_VERTEX) { + gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(s1)); + gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(s2)); + return p1.Distance(p2) < Precision::Confusion(); + } + + return false; +} + } diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.h b/src/Mod/PartDesign/App/FeatureSketchBased.h index 726461ec0..b15318e3f 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.h +++ b/src/Mod/PartDesign/App/FeatureSketchBased.h @@ -28,6 +28,7 @@ #include #include "Feature.h" +class TopoDS_Shape; class TopoDS_Face; class TopoDS_Wire; class gp_Dir; @@ -76,6 +77,9 @@ protected: TopoDS_Shape makeFace(const std::vector&) const; TopoDS_Shape makeFace(std::list&) const; // for internal use only bool isInside(const TopoDS_Wire&, const TopoDS_Wire&) const; + bool isEqualGeometry(const TopoDS_Shape&, const TopoDS_Shape&); + bool isQuasiEqual(const TopoDS_Shape&, const TopoDS_Shape&) const; + void remapSupportShape(const TopoDS_Shape&); /// Extract a face from a given LinkSub static void getUpToFaceFromLinkSub(TopoDS_Face& upToFace, diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp index 13a3b36cc..7d181de8c 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp @@ -399,7 +399,33 @@ void TaskPadParameters::changeEvent(QEvent *e) { TaskBox::changeEvent(e); if (e->type() == QEvent::LanguageChange) { + ui->doubleSpinBox->blockSignals(true); + ui->doubleSpinBox2->blockSignals(true); + ui->lineFaceName->blockSignals(true); + ui->changeMode->blockSignals(true); + int index = ui->changeMode->currentIndex(); ui->retranslateUi(proxy); + ui->changeMode->clear(); + ui->changeMode->addItem(tr("Dimension")); + ui->changeMode->addItem(tr("To last")); + ui->changeMode->addItem(tr("To first")); + ui->changeMode->addItem(tr("Up to face")); + ui->changeMode->addItem(tr("Two dimensions")); + ui->changeMode->setCurrentIndex(index); + + QByteArray upToFace = this->getFaceName(); + int faceId = -1; + bool ok = false; + if (upToFace.indexOf("Face") == 0) { + faceId = upToFace.remove(0,4).toInt(&ok); + } + ui->lineFaceName->setText(ok ? + tr("Face") + QString::number(faceId) : + tr("No face selected")); + ui->doubleSpinBox->blockSignals(false); + ui->doubleSpinBox2->blockSignals(false); + ui->lineFaceName->blockSignals(false); + ui->changeMode->blockSignals(false); } } @@ -446,14 +472,14 @@ bool TaskDlgPadParameters::accept() Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Midplane = %i",name.c_str(),parameter->getMidplane()?1:0); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Length2 = %f",name.c_str(),parameter->getLength2()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Type = %u",name.c_str(),parameter->getMode()); - const char* facename = parameter->getFaceName().data(); + QByteArray facename = parameter->getFaceName(); PartDesign::Pad* pcPad = static_cast(PadView->getObject()); Part::Feature* support = pcPad->getSupport(); - if (support != NULL && facename && facename[0] != '\0') { + if (support != NULL && !facename.isEmpty()) { QString buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])"); buf = buf.arg(QString::fromUtf8(support->getNameInDocument())); - buf = buf.arg(QString::fromUtf8(facename)); + buf = buf.arg(QString::fromUtf8(facename.data())); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = %s", name.c_str(), buf.toStdString().c_str()); } else Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = None", name.c_str()); diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp index b29be9fab..e465f2aaf 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp @@ -363,7 +363,30 @@ void TaskPocketParameters::changeEvent(QEvent *e) { TaskBox::changeEvent(e); if (e->type() == QEvent::LanguageChange) { + ui->doubleSpinBox->blockSignals(true); + ui->lineFaceName->blockSignals(true); + ui->changeMode->blockSignals(true); + int index = ui->changeMode->currentIndex(); ui->retranslateUi(proxy); + ui->changeMode->clear(); + ui->changeMode->addItem(tr("Dimension")); + ui->changeMode->addItem(tr("Through all")); + ui->changeMode->addItem(tr("To first")); + ui->changeMode->addItem(tr("Up to face")); + ui->changeMode->setCurrentIndex(index); + + QByteArray upToFace = this->getFaceName(); + int faceId = -1; + bool ok = false; + if (upToFace.indexOf("Face") == 0) { + faceId = upToFace.remove(0,4).toInt(&ok); + } + ui->lineFaceName->setText(ok ? + tr("Face") + QString::number(faceId) : + tr("No face selected")); + ui->doubleSpinBox->blockSignals(false); + ui->lineFaceName->blockSignals(false); + ui->changeMode->blockSignals(false); } } @@ -407,13 +430,13 @@ bool TaskDlgPocketParameters::accept() //Gui::Command::openCommand("Pocket changed"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Length = %f",name.c_str(),parameter->getLength()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Type = %u",name.c_str(),parameter->getMode()); - const char* facename = parameter->getFaceName().data(); + QByteArray facename = parameter->getFaceName(); PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); Part::Feature* support = pcPocket->getSupport(); - if (support != NULL && facename && facename[0] != '\0') { + if (support != NULL && !facename.isEmpty()) { QString buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])"); buf = buf.arg(QString::fromUtf8(support->getNameInDocument())); - buf = buf.arg(QString::fromUtf8(facename)); + buf = buf.arg(QString::fromUtf8(facename.data())); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = %s", name.c_str(), buf.toStdString().c_str()); } else Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = None", name.c_str());